在文件之间使用全局变量?


207

我对全局变量的工作方式感到困惑。我有一个大型项目,大约有50个文件,我需要为所有这些文件定义全局变量。

我所做的就是在我的项目main.py文件中定义它们,如下所示:

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

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

我想用myListsubfile.py,如下

# ../myproject/subfile.py

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

我尝试过的另一种方法,但也没有用

# ../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])

在里面,subfile.py我有这个:

# ../myproject/subfile.py

# Import globfile
import globfile

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

但同样,它没有用。我应该如何实施呢?我知道当两个文件彼此之间并不真正了解时(子文件不知道主文件),它就不能那样工作,但是我不知道如何在不使用io编写或pickle的情况下做到这一点。我不想做


实际上,您的第二种方法对我来说很好。main.py正确打印出“嘿”。通过“没有用”,您可以更具体地说明您的情况吗?
罗迪

@rodion:导入周期-子文件中的代码尝试导入globfile,它在主体中又将自身导入回来
jsbueno 2012年

1
NameError: name 'myList' is not definedmain.py线print(globfile.myList[0])

Answers:


318

问题是您myList从定义的main.py,但subfile.py需要使用它。这是解决此问题的一种干净方法:将所有全局变量移到一个文件中,我将此文件称为settings.py。该文件负责定义全局变量并初始化它们:

# settings.py

def init():
    global myList
    myList = []

接下来,您subfile可以导入全局变量:

# subfile.py

import settings

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

请注意,subfile它不会调用init()-该任务属于main.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

这样,您就可以实现自己的目标,同时避免多次初始化全局变量。


40
我喜欢一般方法,但不喜欢整个方法init()。只有在首次导入模块时才对它们进行评估,因此完全可以在模块主体中初始化这些变量。
柯克·斯特拉瑟

19
+1柯克:我同意。但是,我的方法可以防止在主程序启动之前其他模块修改globals.myList的情况。
Hai Vu 2012年

2
您应该将其称为全局变量以外的其他名称,这是一个内置名称。PyLint发出警告:“重新定义内置的'globals'(redefined-builtin)”
twasbrillig 2015年

谢谢。任何想法如何通过使用此文件结构来消除Eclipse PyDev中出现的“从导入中删除未定义的变量”错误(即,从settings.py导入全局变量)?我不得不禁用PyDev中的错误,这是不理想的。
Franck Dernoncourt

@FranckDernoncourt对不起,我没有使用Eclipse,所以我比你更笨。
Hai Vu

93

请参阅Python文档,了解如何在模块之间共享全局变量

在单个程序中的各个模块之间共享信息的规范方法是创建一个特殊的模块(通常称为config或cfg)。

config.py:

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

将配置模块导入应用程序的所有模块中;然后该模块就可以作为全局名称使用。

main.py:

import config
print (config.x)

要么

from config import x
print (x)

通常,不要使用 from modulename import *。这样做会使导入者的名称空间变得混乱,并使短毛猫更难检测未定义的名称。


1
救生员-仅用于该链接!
toonarmycaptain

4
这似乎比接受的答案更干净。
JoeyC

2
请注意,您无法x使用进行设置from config import x,只能使用import config
Yariv

1
最简单的解决方案!谢谢
user1297406

22

您可以将Python全局变量视为“模块”变量-因此,它们比C语言中的传统“全局变量”有用得多。

全局变量实际上是在模块的中定义的__dict__,可以从模块外部作为模块属性进行访问。

因此,在您的示例中:

# ../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])

和:

# ../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")

1
哇,通常人们希望两个互相导入的文件陷入无限循环。
Nikhil VJ

2
ha乍看起来是这样,不是吗?def stuff()中发生的情况是,导入不会在文件加载时运行。.仅在调用stuff()函数时运行。因此,从main开始,我们导入子文件,然后调用subfile.stuff(),然后再导入main ... no循环,只需在main中导入一次。请参阅subfile.py示例中有关导入周期的注释。
约翰

11

使用from your_file import *应该可以解决您的问题。它定义了所有内容,以便全局可用(当然,导入中的局部变量除外)。

例如:

##test.py:

from pytest import *

print hello_world

和:

##pytest.py

hello_world="hello world!"

4
除非您为一个这样的变量赋值
jsbueno 2012年

5
我个人import *不惜一切代价避免使用,以便引用是显式的(并且不会造成混淆)。此外,您何时真正*在任何模块中实际使用过所有“ ”引用?
ThorSummoner 2014年

19
请勿导入*。您的全局变量将不再保持同步。每个模块都有自己的副本。在一个文件中更改变量不会在另一个文件中反映出来。docs.python.org/2/faq/…中
Isa Hassen

8

Hai Vu的答案很棒,只需评论一下:

如果要在其他模块中使用全局变量并且要动态设置全局变量,请在设置全局变量后注意导入其他模块,例如:

# 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

4

您的第二次尝试将非常有效,实际上是处理要全局使用的变量名的好方法。但是您在最后一行有名称错误。应该是这样的:

# ../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])

看到最后一行?myList是globfile(而不是子文件)的attr。这将根据您的需要工作。

麦克风

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.