简体   繁体   English

来自不同文件 Python 的全局变量

[英]Global Variable from a different file Python

So I have two different files somewhat like this:所以我有两个不同的文件,有点像这样:

file1.py文件1.py

from file2 import *
foo = "bar"
test = SomeClass()

file2.py文件2.py

class SomeClass :
    def __init__ (self):
        global foo
        print foo

However I cannot seem to get file2 to recognize variables from file1 even though its imported into file1 already.但是我似乎无法让 file2 识别来自 file1 的变量,即使它已经导入到 file1 中。 It would be extremely helpful if this is possible in some way.如果这在某种程度上是可能的,那将是非常有帮助的。

Importing file2 in file1.py makes the global (ie, module level) names bound in file2 available to following code in file1 -- the only such name is SomeClass .导入file2file1.py使得全球(即,模块级)的约束名称file2可用下面的代码在file1 -只有这样的名字是SomeClass It does not do the reverse: names defined in file1 are not made available to code in file2 when file1 imports file2 .没有做反向:在定义的名称file1不提供给代码file2 ,当file1导入file2 This would be the case even if you imported the right way ( import file2 , as @nate correctly recommends) rather than in the horrible, horrible way you're doing it (if everybody under the Sun forgot the very existence of the construct from ... import * , life would be so much better for everybody).即使您以正确的方式import file2import file2 ,正如@nate 正确推荐的那样),而不是以您正在做的可怕的、可怕的方式import file2 (如果太阳下的每个人都忘记了from ... import * ,生活会好得多为大家)。

Apparently you want to make global names defined in file1 available to code in file2 and vice versa.显然,你想在定义的全局名称file1中的代码可用file2 反之亦然。 This is known as a "cyclical dependency" and is a terrible idea (in Python, or anywhere else for that matter).这被称为“循环依赖”并且是一个糟糕的想法(在 Python 或其他任何地方)。

So, rather than showing you the incredibly fragile, often unmaintainable hacks to achieve (some semblance of) a cyclical dependency in Python, I'd much rather discuss the many excellent way in which you can avoid such terrible structure.因此,与其向您展示在 Python 中实现(某种表面上的)循环依赖的极其脆弱、通常无法维护的 hack,我宁愿讨论许多可以避免这种可怕结构的极好方法。

For example, you could put global names that need to be available to both modules in a third module (eg file3.py , to continue your naming streak;-) and import that third module into each of the other two ( import file3 in both file1 and file2 , and then use file3.foo etc, that is, qualified names, for the purpose of accessing or setting those global names from either or both of the other modules, not barenames).例如,您可以将需要对两个模块都可用的全局名称放在第三个模块中(例如file3.py ,以继续您的命名file3.py ;-)并将该第三个模块导入其他两个模块中的每一个(在两个模块中都import file3 file1file2 ,然后使用file3.foo等,即限定名称,用于从其他模块中的一个或两个访问或设置这些全局名称,而不是裸名)。

Of course, more and more specific help could be offered if you clarified (by editing your Q) exactly why you think you need a cyclical dependency (just one easy prediction: no matter what makes you think you need a cyclical dependency, you're wrong;-).当然,如果您明确(通过编辑 Q)您认为需要循环依赖的确切原因(只是一个简单的预测:无论是什么让您认为需要循环依赖,您是错误的;-)。

When you write当你写

from file2 import *

it actually copies the names defined in file2 into the namespace of file1 .它实际上将file2定义的名称复制file1的命名空间中。 So if you reassign those names in file1 , by writing因此,如果您在file1重新分配这些名称,请写入

foo = "bar"

for example, it will only make that change in file1 , not file2 .例如,它只会在file1进行更改,而不是file2 Note that if you were to change an attribute of foo , say by doing请注意,如果您要更改foo属性,请说

foo.blah = "bar"

then that change would be reflected in file2 , because you are modifying the existing object referred to by the name foo , not replacing it with a new object.那么该更改将反映在file2 ,因为您正在修改由名称foo引用的现有对象,而不是用新对象替换它。

You can get the effect you want by doing this in file1.py :您可以通过在file1.py执行此操作来获得您想要的效果:

import file2
file2.foo = "bar"
test = SomeClass()

(note that you should delete from foo import * ) although I would suggest thinking carefully about whether you really need to do this. (请注意,您应该from foo import *删除),尽管我建议您仔细考虑您是否真的需要这样做。 It's not very common that changing one module's variables from within another module is really justified.从另一个模块中更改一个模块的变量确实是合理的,这并不常见。

from file2 import * is making copies. from file2 import *正在制作副本。 You want to do this:你想这样做:

import file2
print file2.foo
print file2.SomeClass()

global is a bit of a misnomer in Python, module_namespace would be more descriptive. global在 Python 中有点用词不当, module_namespace会更具描述性。

The fully qualified name of foo is file1.foo and the global statement is best shunned as there are usually better ways to accomplish what you want to do. foo的完全限定名称是file1.foo并且最好避免使用 global 语句,因为通常有更好的方法来完成您想要做的事情。 (I can't tell what you want to do from your toy example.) (我无法从您的玩具示例中看出您想做什么。)

After searching, I got this clue: https://instructobit.com/tutorial/108/How-to-share-global-variables-between-files-in-Python搜索后,我得到了这个线索: https : //instructobit.com/tutorial/108/How-to-share-global-variables-between-files-in-Python

the key is: turn on the function to call the variabel that set to global if a function activated.关键是:如果一个函数被激活,打开函数调用设置为全局的变量。

then import the variabel again from that file.然后从该文件再次导入变量。

i give you the hard example so you can understood:我给你举了一个很难的例子,所以你可以理解:

file chromy.py文件chromy.py

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def opennormal():
    global driver
    options = Options()
    driver = webdriver.Chrome(chrome_options=options)

def gotourl(str):
    url = str
    driver.get(url)

file tester.py文件 tester.py

from chromy import * #this command call all function in chromy.py, but the 'driver' variable in opennormal function is not exists yet. run: dir() to check what you call.

opennormal() #this command activate the driver variable to global, but remember, at the first import you not import it

#then do this, this is the key to solve:
from chromy import driver #run dir() to check what you call and compare with the first dir() result.

#because you already re-import the global that you need, you can use it now

url = 'https://www.google.com'
gotourl(url)

That's the way you call the global variable that you set in a function.这就是调用在函数中设置的全局变量的方式。 cheers don't forget to give credit欢呼不要忘记给予信任

while I do the test following the idea of @robertspierre to put all global variables in a glv.py file and then import it in other files where it is used, the demo codes is given bellow, hope it helps:当我按照@robertspierre 的想法进行测试时,将所有全局变量放在一个 glv.py 文件中,然后将其导入到其他使用它的文件中,下面给出了演示代码,希望对您有所帮助:

  1. the global variable file, glv.py:全局变量文件,glv.py:
# glv.py
glvB = True
glvA = 100
glvS = "tiger"
glvList = [1, 2, 3]
glvTuple = (1, "a")
glvDict = {"Name": "tiger", "age": 100}
  1. sub1.py, it's a file that will import the glv.py file. sub1.py,这是一个将导入 glv.py 文件的文件。 Two functions are defined to show and change the global variable data in glv.py, showData() and changeData(), glv.py中定义了两个函数来显示和改变全局变量数据,showData()和changeData(),
# sub1.py
import glv


def showData():
    print(f"*****glv in sub1*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


def changeData():
    glv.glvB = False
    glv.glvA = 200
    glv.glvS = "bactone"
    glv.glvList = [4, 5, 6]
    glv.glvTuple = (2, "b")
    glv.glvDict = {"Name": "bactone", "age": 0}
  1. sub2.py is another file: sub2.py 是另一个文件:
# sub2.py

import glv


def showData():
    print(f"*****glv in sub2*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


def changeData():
    glv.glvB = True
    glv.glvA = 300
    glv.glvS = "bactone"
    glv.glvList = [7, 8, 9]
    glv.glvTuple = (3, "c")
    glv.glvDict = {"Name": "bactone1", "age": 10}
  1. finally we test the global variable in main.py:最后我们在 main.py 中测试全局变量:
import glv
import sub1
import sub2


def showData():
    print(f"*****initial global variable values*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


if __name__ == "__main__":

    showData()  # show initial global variable
    sub1.showData()  # show global variable in sub1
    sub1.changeData()  # change global variable in sub1
    sub2.showData()  # show global variable in sub2
    sub2.changeData()  # change global variable in sub2
    sub1.showData()  # show global variable in sub1 again

the results turns out to be:结果是:

*****initial global variable values*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}

*****glv in sub1*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}

*****glv in sub2*****
glvB=False
glvA=200
glvS=bactone
glvList=[4, 5, 6]
glvTuple=(2, 'b')
glvDict={'Name': 'bactone', 'age': 0}

*****glv in sub1*****
glvB=True
glvA=300
glvS=bactone
glvList=[7, 8, 9]
glvTuple=(3, 'c')
glvDict={'Name': 'bactone1', 'age': 10}

we can see all kinds of data type works and the change of global variable is automatically reloaded.我们可以看到各种数据类型都有效,并且全局变量的更改会自动重新加载。

I came to the conclusion that you can import globals, but you can not change them once imported.我得出的结论是,您可以导入全局变量,但一旦导入就无法更改它们。 The only exception is if you pass them as arguments.唯一的例外是如果您将它们作为参数传递。 I would love to be wrong on this, so let me know if there is a way to effectively re import updated globals.我很想在这方面出错,所以让我知道是否有办法有效地重新导入更新的全局变量。 The two codes below will run.下面的两个代码将运行。

from b import *  # import all from b.py

global alpha  # declare globals
global bravo
global charlie

alpha = 10  # assign values to globals
bravo = 20
charlie = 15


def run_one():
    one(alpha)  # pass the global to b.py


def run_two():
    two()  # rely on import statement in b.py


def run_three():
    global charlie  # declare the global to change it
    charlie = 40  # change the value for charlie
    print("charlie:", charlie, " --> global value changed in a.py run_three()")


def run_three_again():  # print charlie again from b.py
    three()


def run_four():  # re import charlie in b.py
    four()


if __name__ == "__main__":  # prevent the code from being executed when b.py imports a.py
    run_one()  # run through all the functions in a.py
    run_two()
    run_three()
    run_three_again()
    run_four()

Also:还:

from a import *  # import all from a.py


def one(alpha):
    print("alpha:  ", alpha, " --> global passed as argument in one()")


def two():
    print("bravo:  ", bravo, " --> global imported from a.py in two()")


def three():
    print("charlie:", charlie, " --> global imported from a.py in three() but is not changed")


def four():
    from a import charlie  # re import charlie from a.py
    print("charlie:", charlie, " --> global re-imported in four() but does not change")

The output from the print statements are below:打印语句的输出如下:

alpha:   10  --> global passed as argument in one()
bravo:   20  --> global imported from a.py in two()
charlie: 40  --> global value changed in a.py run_three()
charlie: 15  --> global imported from a.py in three() but is not changed
charlie: 15  --> global re-imported in four() but does not change

All given answers are wrong.所有给出的答案都是错误的。 It is impossible to globalise a variable inside a function in a separate file.不可能在单独的文件中将函数内的变量全球化。

只需将您的全局变量放在您要导入的文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM