python-2.7 %s - Variable locale référencée avant l'affectation en Python?




definir globale (4)

Lorsque Python analyse le corps d’une définition de fonction et rencontre une affectation telle que

feed = ...

Python interprète le 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 nécessairement être au début de la définition de la fonction, mais c'est là qu'elle est généralement placée. Partout où elle est placée, la déclaration globale fait feed une variable globale partout dans la fonction.

Sans l'instruction globale, puisque le feed est considéré comme une variable locale, lorsque Python s'exécute

feed = feed + 1,

Python évalue d'abord le côté droit et essaie de rechercher la valeur du flux. La première fois qu'il trouve du feed est indéfini. D'où l'erreur.

Le moyen le plus court de corriger le code consiste à ajouter global feed au début de onLoadFinished . Le meilleur moyen est d'utiliser une classe:

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

Le problème avec les fonctions qui mutent les variables globales est qu’il est plus difficile de manipuler 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 les plus gros programmes plus difficiles à comprendre.

En évitant les globales en mutation, à long terme, votre code sera plus facile à comprendre, à tester et à maintenir.

J'utilise la bibliothèque PyQt pour prendre une capture d'écran d'une page Web, puis lire un fichier CSV de différentes URL. Je garde un flux variable qui s'incrémente chaque fois qu'une URL est traitée et doit donc être incrémentée au 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?


Mettez une déclaration globale en haut de votre fonction et vous devriez être bien:

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 exactement avec la même erreur:

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 disiez 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 , cela génère une erreur.


Comme l'interpréteur Python lit la définition d'une fonction (ou, je pense, même un bloc de code en retrait), toutes les variables affectées à l' intérieur de la fonction sont ajoutées aux sections locales pour cette fonction. Si un local n'a pas de définition avant une affectation, l'interpréteur Python ne sait pas quoi faire, il génère donc cette erreur.

La solution ici est d'ajouter

global feed

à votre fonction (généralement près du haut) pour indiquer à l'interpréteur que la variable de flux n'est pas locale à cette fonction.


Si vous avez besoin du résultat de la commande que vous appelez, vous pouvez utiliser subprocess.check_output (Python 2.7+).

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

Notez également le paramètre shell .

Si shell a la valeur True , la commande spécifiée sera exécutée via le shell. Cela peut être utile si vous utilisez principalement Python pour le flux de contrôle amélioré proposé par la plupart des interpréteurs de commandes système et que vous souhaitez tout de même accéder facilement à d'autres fonctionnalités du interpréteur de commandes, telles que les pipes shell, les jokers de nom de fichier, le développement de variables d'environnement et l'extension de ~ vers le domicile de l'utilisateur. annuaire. Cependant, notez que Python lui-même offre des implémentations de nombreuses fonctionnalités similaires à celles du shell (notamment glob , fnmatch , os.walk() , os.path.expandvars() , os.path.expanduser() et shutil ).







python python-2.7 python-3.x variable-assignment