Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 变量范围(带线程)_Python_Multithreading - Fatal编程技术网

Python 变量范围(带线程)

Python 变量范围(带线程),python,multithreading,Python,Multithreading,我有两个模块中的以下代码 模块“主”: 模块“B”: 如果我运行此代码,我会得到: a = 0 Starting Thread-1 api_a() Exiting Thread-1 a = 0 为什么变量“a”没有设置为“1” 如果我激活模块“main”(api_a())中注释的代码行,变量“a”将设置为“1”。为什么在通过线程调用函数api_a()时不设置变量 在示例代码中,我跳过了使用锁来确保代码线程安全 有什么想法吗 提前多谢了 Thomas发生这种行为,因为您将main.py作为参数传

我有两个模块中的以下代码

模块“主”:

模块“B”:

如果我运行此代码,我会得到:

a = 0
Starting Thread-1
api_a()
Exiting Thread-1
a = 0
为什么变量“a”没有设置为“1”

如果我激活模块“main”(api_a())中注释的代码行,变量“a”将设置为“1”。为什么在通过线程调用函数api_a()时不设置变量

在示例代码中,我跳过了使用锁来确保代码线程安全

有什么想法吗

提前多谢了


Thomas

发生这种行为,因为您将
main.py
作为参数传递给python(
python main.py

当您以这种方式执行脚本时,python将
main
模块解释为
\uuu main\uuu
,但是
b
模块仍然更新
main.a
变量而不是
\uu main\uuu.a
,因为
b
已将main.py模块重新导入为
main

因此,为了使其正常工作,我们可以从
b
模块的角度更新
api\u a
函数中的
main\u.a
,或者从
\u main\u
模块的角度打印
main.a
变量,而不是
\u main\u.a

def api_a():
    print("api_a()")
    import sys
    sys.modules['__main__'].a = 1


docs

我看到了这个问题,但它很微妙,部分与您使用循环导入有关,
“main”
模块和
“main”
模块都是其中之一。换句话说,您的“main”模块会被导入两次,一次是在名称
“\uuuu main\uuuuu”
下,一次是在名称“main”下,并且模块的每个副本都将有单独的全局文件。在本例中,只有名为“main”的全局变量被更新。如果你能提醒我的话,我会在稍后给出更好的答案。而且这个问题与你使用线程无关。如果在
main()
函数中,而不是直接调用
b.b_进程()
来启动线程,则会遇到完全相同的问题。另外,另一个启发性的演示是运行
python-c'import-main;main.main()
它将按预期工作。因此,如果我理解正确,问题只会因为“main”而出现。意思是,如果我将al逻辑从主模块移动到一个单独的模块(我们称之为“C”),然后从“main”和“B”调用C的函数,它就会工作?是的,没错@Artemiy下面的完整答案是正确的。我编辑了你的答案,做了一些小的工作更正,但这是正确的。尽管我不建议您使用
sys.modules
。实际上,OP有一个完美的有问题的设计选择风暴——每一个选择本身都是合理的(使用全局变量、使用循环导入、使用多个模块而不将它们放入包中等等)——这使得这个问题比正常情况下更加明显。关键是,他们可能应该重构代码。这个方法是线程安全的吗?或者我们需要使用锁定来保证线程安全吗?@variable它不是线程安全的。我也同意@Iguananaut的观点,不建议这样使用
sys.modules
a = 0
Starting Thread-1
api_a()
Exiting Thread-1
a = 0
def api_a():
    print("api_a()")
    import sys
    sys.modules['__main__'].a = 1
def main():
    ...
    thread_B.join()
    import sys
    print("a = " + str(sys.modules['main'].a))