¿Variable local referenciada antes de la asignación en Python?

Estoy utilizando la biblioteca de PyQt para tomar una captura de pantalla de una página web y luego leer un archivo CSV de diferentes URL. Mantengo una fuente variable que se incrementa cada vez que se procesa una URL y, por lo tanto, debería boost la cantidad de URL.

Aquí está el código:

webpage = QWebPage() fo = open("C:/Users/Romi/Desktop/result1.txt", "w") feed = 0 def onLoadFinished(result): #fo.write( column1[feed])#, column2[feed], urls[feed]) #feed = 0 if not result: print "Request failed" fo.write(column1[feed]) fo.write(',') fo.write(column2[feed]) fo.write(',') #fo.write(urls[feed]) fo.write(',') fo.write('404,image not created\n') feed = feed + 1 sys.exit(1) save_page(webpage, outputs.pop(0)) # pop output name from list and save if urls: url = urls.pop(0) # pop next url to fetch from list webpage.mainFrame().load(QUrl(url)) fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n') fo.write(',') fo.write(column2[feed]) fo.write(',') #fo.write(urls[feed]) fo.write(',') fo.write('200,image created\n') feed = feed + 1 else: app.quit() # exit after last url webpage.connect(webpage, SIGNAL("loadFinished(bool)"), onLoadFinished) webpage.mainFrame().load(QUrl(urls.pop(0))) #fo.close() sys.exit(app.exec_()) 

Me da el error:

 local variable feed referenced before the assignment at fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n') 

¿Alguna idea de por qué?

Cuando Python analiza el cuerpo de una definición de función y encuentra una asignación como

 feed = ... 

Python interpreta el feed como una variable local de forma predeterminada. Si no desea que sea una variable local, debe poner

 global feed 

en la definición de la función. La statement global no tiene que estar al principio de la definición de la función, pero ahí es donde normalmente se coloca. Donde sea que se coloque, la statement global hace que se feed una variable global en todas partes de la función.

Sin la statement global, ya que el feed se toma como una variable local, cuando Python se ejecuta

 feed = feed + 1, 

Python evalúa primero el lado derecho e intenta buscar el valor del feed. La primera vez a través de ella encuentra que el feed no está definido. De ahí el error.

La forma más corta de parchear el código es agregar global feed al principio de onLoadFinished . La mejor manera es usar una clase:

 class Page(object): def __init__(self): self.feed = 0 def onLoadFinished(self, result): ... self.feed += 1 

El problema de tener funciones que mutan variables globales es que hace que sea más difícil asimilar tu código. Las funciones ya no son unidades aisladas. Su interacción se extiende a todo lo que afecta o es afectado por la variable global. Por lo tanto, hace que los progtwigs más grandes sean más difíciles de entender.

Al evitar la mutación de elementos globales, a la larga, su código será más fácil de entender, probar y mantener.

Ponga una statement global en la parte superior de su función y debe ser bueno:

 def onLoadFinished(result): global feed ... 

Para demostrar lo que quiero decir, mira esta pequeña prueba:

 x = 0 def t(): x += 1 t() 

esto explota con su mismo error exacto donde:

 x = 0 def t(): global x x += 1 t() 

no.

La razón de esto es que, dentro de t , Python piensa que x es una variable local. Además, a menos que explícitamente le digas que x es global, intentará usar una variable local llamada x en x += 1 . Pero, dado que no hay una x definida en el ámbito local de t , produce un error.

Cuando el intérprete de Python lee la definición de una función (o, creo, incluso un bloque de código con sangría), todas las variables que se asignan dentro de la función se agregan a los locales para esa función. Si un local no tiene una definición antes de una asignación, el intérprete de Python no sabe qué hacer, por lo que produce este error.

La solución aquí es agregar

 global feed 

a su función (generalmente cerca de la parte superior) para indicar al intérprete que la variable de alimentación no es local para esta función.