2012-10-23 14 views
85

Sono un po 'confuso su come funzionano le variabili globali. Ho un grande progetto, con circa 50 file, e ho bisogno di definire variabili globali per tutti quei file.Utilizzo di variabili globali tra file?

Quello che ho fatto è stato definirli nei miei progetti main.py di file, come segue:

# ../myproject/main.py 

# Define global myList 
global myList 
myList = [] 

# Imports 
import subfile 

# Do something 
subfile.stuff() 
print(myList[0]) 

che sto cercando di utilizzare myList in subfile.py, come seguendo

# ../myproject/subfile.py 

# Save "hey" into myList 
def stuff(): 
    globals()["myList"].append("hey") 

Un altro senso che provato, ma non ha funzionato né

# ../myproject/main.py 

# Import globfile  
import globfile 

# Save myList into globfile 
globfile.myList = [] 

# Import subfile 
import subfile 

# Do something 
subfile.stuff() 
print(globfile.myList[0]) 

E dentro subfile.py ho avuto questa:

# ../myproject/subfile.py 

# Import globfile 
import globfile 

# Save "hey" into myList 
def stuff(): 
    globfile.myList.append("hey") 

Ma ancora una volta, non ha funzionato. Come dovrei implementarlo? Capisco che non può funzionare in questo modo, quando i due file non si conoscono veramente bene (bene il subfile non sa main), ma non riesco a pensare a come farlo, senza usare io scrivere o pickle, che Non voglio farlo.

+0

In realtà, il tuo secondo approccio funziona perfettamente per me. main.py stampa correttamente "hey". Puoi essere più specifico su ciò che tu per "non ha funzionato"? – rodion

+0

@rodion: cicli di importazione: il codice nel file secondario tenta di importare globfile, che nel suo corpo si importa indietro – jsbueno

+1

'NameError: nome 'myList' non è definito' da' main.py' linea 'print (globfile.myList [0 ]) ' –

risposta

156

Il problema è definito da myList main.py, ma subfile.py ha bisogno di usarlo. Ecco un modo pulito per risolvere questo problema: spostare tutti i globali in un file, io chiamo questo file settings.py.Questo file è responsabile della definizione globali e l'inizializzazione:

# settings.py 

def init(): 
    global myList 
    myList = [] 

Avanti, il vostro file secondario può importare globali:

# subfile.py 

import settings 

def stuff(): 
    settings.myList.append('hey') 

noti che file secondario non chiama init() - questo compito appartiene alla principale. py:

# main.py 

import settings 
import subfile 

settings.init()   # Call only once 
subfile.stuff()   # Do stuff with global var 
print settings.myList[0] # Check the result 

In questo modo, raggiungi il tuo obiettivo evitando di inizializzare le variabili globali più di una volta.

+15

Mi piace l'approccio generale, ma non l'intero 'init()' cose. I moduli vengono valutati solo la prima volta che vengono importati, quindi è perfettamente OK inizializzare tali variabili nel corpo del modulo. –

+8

+1 Kirk: sono d'accordo. Tuttavia, il mio approccio impedisce il caso in cui altri moduli modificano globals.myList prima dell'avvio del programma principale. –

+2

Dovresti chiamarlo qualcosa di diverso dai globals, che è un nome incorporato. PyLint dà l'avvertimento: "Ridefinizione di 'globals' incorporati (redefined-builtin)" – twasbrillig

12

Utilizzare from your_file import * per risolvere i problemi. Definisce tutto in modo che sia globalmente disponibile (ad eccezione delle variabili locali nelle importazioni ovviamente).

ad esempio:

##test.py: 

from pytest import * 

print hello_world 

e:

##pytest.py 

hello_world="hello world!" 
+3

Tranne se si assegna ad una di queste variabili – jsbueno

+2

io personalmente evito l'uso di" import * "a tutti i costi in modo che i riferimenti siano espliciti (e non confusi), Inoltre, quando mai si è effettivamente usato tutto" '*' "riferimenti in qualsiasi modulo? – ThorSummoner

+8

NON importare *. Le tue variabili globali non rimarranno più sincronizzate. Ogni modulo riceve la propria copia. Cambiare la variabile in un file non si rifletterà in un altro. E 'anche messo in guardia contro in https://docs.python.org/2/faq/programming.html#how-do-i-share-global-variables-across-modules –

14

Si può pensare di variabili globali Python come variabili "modulo" - e come tali sono molto più utili rispetto ai tradizionali "variabili globali "da C.

Una variabile globale viene effettivamente definita nel modulo __dict__ e può essere richiamata dall'esterno di tale modulo come attributo di modulo.

Quindi, nel tuo esempio:

# ../myproject/main.py 

# Define global myList 
# global myList - there is no "global" declaration at module level. Just inside 
# function and methods 
myList = [] 

# Imports 
import subfile 

# Do something 
subfile.stuff() 
print(myList[0]) 

E:

# ../myproject/subfile.py 

# Save "hey" into myList 
def stuff(): 
    # You have to make the module main available for the 
    # code here. 
    # Placing the import inside the function body will 
    # usually avoid import cycles - 
    # unless you happen to call this function from 
    # either main or subfile's body (i.e. not from inside a function or method) 
    import main 
    main.mylist.append("hey") 
2

tuo 2 ° tentativo funziona perfettamente, e in realtà è un ottimo modo per gestire i nomi delle variabili che si desidera avere a disposizione globalmente. Ma hai un errore di nome nell'ultima riga. Ecco come dovrebbe essere:

# ../myproject/main.py 

# Import globfile  
import globfile 

# Save myList into globfile 
globfile.myList = [] 

# Import subfile 
import subfile 

# Do something 
subfile.stuff() 
print(globfile.myList[0]) 

Vedere l'ultima riga? myList è un attr di globfile, non subfile. Funzionerà come vuoi tu.

Mike

6

Hai Vu risposta funziona alla grande, solo un commento:

Nel caso in cui si utilizza il mondiale in altro modulo e si desidera impostare il mondiale in modo dinamico, prestare attenzione ad importare altri moduli dopo aver impostato le variabili globali , per esempio:

# settings.py 
def init(arg): 
    global myList 
    myList = [] 
    mylist.append(arg) 


# subfile.py 
import settings 

def print(): 
    settings.myList[0] 


# main.py 
import settings 
settings.init("1st")  # global init before used in other imported modules 
         # Or else they will be undefined 

import subfile  
subfile.print()   # global usage 
7

documento See, in Python su sharing global variables across modules:

The canonical way to share information across modules within a single program is to create a special module (often called config or cfg).

config.py:

x = 0 # Default value of the 'x' configuration setting 

Import the config module in all modules of your application; the module then becomes available as a global name.

main.py:

import config 
print config.x 

or

from config import x 
print x 

In general, don’t use from modulename import *. Doing so clutters the importer’s namespace, and makes it much harder for linters to detect undefined names.