J'utilise la bibliothèque PyQt pour prendre une capture d'écran d'une page Web, puis pour lire un fichier CSV contenant différentes URL. Je garde un flux variable qui s'incrémente chaque fois qu'une adresse URL est traitée et doit donc incrémenter le nombre d'URL.
Voici le code:
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_())
Cela me donne l'erreur:
local variable feed referenced before the assignment at fo.write(column1[feed])#,column2[feed],urls[feed],'200','image created','/n')
Une idée pourquoi?
When Python analyse le corps d'une définition de fonction et rencontre une affectation telle que
feed = ...
Python interprète feed
comme une variable locale par défaut. Si vous ne souhaitez pas que ce soit une variable locale, vous devez mettre
global feed
dans la définition de la fonction. L'instruction globale ne doit pas obligatoirement figurer au début de la définition de la fonction, mais c'est là qu'elle est habituellement placée. Où qu’elle soit placée, la déclaration globale fait de feed
une variable globale partout dans la fonction.
Sans la déclaration globale, puisque feed
est considéré comme une variable locale, lorsque Python est exécuté
feed = feed + 1,
Python évalue le côté droit en premier et tente de rechercher la valeur du fil. La première fois qu'il trouve feed
n'est pas défini. D'où l'erreur.
Le moyen le plus rapide de corriger le code est d’ajouter global feed
au début de onLoadFinished
. La meilleure façon est d'utiliser une classe:
class Page(object):
def __init__(self):
self.feed = 0
def onLoadFinished(self, result):
...
self.feed += 1
Le problème des fonctions qui mutent les variables globales est qu’il est plus difficile de coder votre code. Les fonctions ne sont plus des unités isolées. Leur interaction s'étend à tout ce qui affecte ou est affecté par la variable globale. Cela rend donc plus difficile la compréhension des grands programmes.
En évitant les globals en mutation, votre code sera plus facile à comprendre, à tester et à maintenir à long terme.
Mettez une déclaration globale au sommet de votre fonction et vous devriez être bon:
def onLoadFinished(result):
global feed
...
Pour démontrer ce que je veux dire, regardez ce petit test:
x = 0
def t():
x += 1
t()
cela explose avec votre même erreur exacte que:
x = 0
def t():
global x
x += 1
t()
ne fait pas.
La raison en est que, dans t
, Python pense que x
est une variable locale. De plus, à moins que vous ne lui indiquiez explicitement que x
est global, il essaiera d’utiliser une variable locale nommée x
dans x += 1
. Mais, comme il n'y a pas de x
défini dans la portée locale de t
, il génère une erreur.
Comme l'interprète Python lit la définition d'une fonction (ou, je pense, même un bloc de code en retrait)), toutes les variables qui sont assignées à à l'intérieur de la fonction sont ajouté aux sections locales de cette fonction Si un local n’a pas de définition avant une affectation, l’interprète Python ne sait pas quoi faire; il renvoie donc cette erreur.
La solution ici est d'ajouter
global feed
à votre fonction (généralement près du haut) pour indiquer à l'interprète que la variable de fil n'est pas locale à cette fonction.