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

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

我对全局变量的工作方式感到困惑。我有一个大型项目,大约有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的情况下做到这一点。我不想做

I’m bit confused about how the global variables work. I have a large project, with around 50 files, and I need to define global variables for all those files.

What I did was define them in my projects main.py file, as following:

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

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

I’m trying to use myList in subfile.py, as following

# ../myproject/subfile.py

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

An other way I tried, but didn’t work either

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

And inside subfile.py I had this:

# ../myproject/subfile.py

# Import globfile
import globfile

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

But again, it didn’t work. How should I implement this? I understand that it cannot work like that, when the two files don’t really know each other (well subfile doesn’t know main), but I can’t think of how to do it, without using io writing or pickle, which I don’t want to do.


回答 0

问题是您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

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

The problem is you defined myList from main.py, but subfile.py needs to use it. Here is a clean way to solve this problem: move all globals to a file, I call this file settings.py. This file is responsible for defining globals and initializing them:

# settings.py

def init():
    global myList
    myList = []

Next, your subfile can import globals:

# subfile.py

import settings

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

Note that subfile does not call init()— that task belongs to 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

This way, you achieve your objective while avoid initializing global variables more than once.


回答 1

请参阅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 *。这样做会使导入者的命名空间变得混乱,并使短毛猫更难检测未定义的名称。

See Python’s document on 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.


回答 2

您可以将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")

You can think of Python global variables as “module” variables – and as such they are much more useful than the traditional “global variables” from C.

A global variable is actually defined in a module’s __dict__ and can be accessed from outside that module as a module attribute.

So, in your example:

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

And:

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

回答 3

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

例如:

##test.py:

from pytest import *

print hello_world

和:

##pytest.py

hello_world="hello world!"

Using from your_file import * should fix your problems. It defines everything so that it is globally available (with the exception of local variables in the imports of course).

for example:

##test.py:

from pytest import *

print hello_world

and:

##pytest.py

hello_world="hello world!"

回答 4

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

Hai Vu answer works great, just one comment:

In case you are using the global in other module and you want to set the global dynamically, pay attention to import the other modules after you set the global variables, for example:

# 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

回答 5

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

# ../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。这将根据您的需要工作。

麦克风

Your 2nd attempt will work perfectly, and is actually a really good way to handle variable names that you want to have available globally. But you have a name error in the last line. Here is how it should be:

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

See the last line? myList is an attr of globfile, not subfile. This will work as you want.

Mike