Python 在运行时更改导入函数的全局变量

Python 在运行时更改导入函数的全局变量,python,python-3.x,python-multithreading,Python,Python 3.x,Python Multithreading,我试图使一个较大程序的不同文件中的函数互相发送消息。有一个没有返回语句的函数。在测试示例中,如果我在一个文件中执行以下操作,我可以更改全局变量并在运行时检测其更改: one_file.py import time import threading has_run = False def processing_function(): global has_run time.sleep(5) has_run = True start = time.clock() thr

我试图使一个较大程序的不同文件中的函数互相发送消息。有一个没有返回语句的函数。在测试示例中,如果我在一个文件中执行以下操作,我可以更改全局变量并在运行时检测其更改:

one_file.py

import time
import threading
has_run = False

def processing_function():
    global has_run
    time.sleep(5)
    has_run = True

start = time.clock()

thread = threading.Thread(target=processing_function)
thread.start()

while True:
    print(has_run)
    time.sleep(0.5)
    if (10/3600) < time.clock() - start:
        break
import time
has_run = False

def processing_function():
    global has_run
    time.sleep(5)
    has_run = True
from file1 import processing_function, has_run
import time
import threading

start = time.clock()
thread = threading.Thread(target=processing_function)
thread.start()

while True:
    print(has_run)
    time.sleep(0.5)
    if (10/3600) < time.clock() - start:
        break
file2.py

import time
import threading
has_run = False

def processing_function():
    global has_run
    time.sleep(5)
    has_run = True

start = time.clock()

thread = threading.Thread(target=processing_function)
thread.start()

while True:
    print(has_run)
    time.sleep(0.5)
    if (10/3600) < time.clock() - start:
        break
import time
has_run = False

def processing_function():
    global has_run
    time.sleep(5)
    has_run = True
from file1 import processing_function, has_run
import time
import threading

start = time.clock()
thread = threading.Thread(target=processing_function)
thread.start()

while True:
    print(has_run)
    time.sleep(0.5)
    if (10/3600) < time.clock() - start:
        break
从file1导入处理函数,运行
导入时间
导入线程
开始=时间。时钟()
线程=线程。线程(目标=处理函数)
thread.start()
尽管如此:
打印(已运行)
睡眠时间(0.5)
如果(10/3600)
如果现在运行file2.py,它只会多次打印False


为什么这个导入的全局变量没有被正在运行的进程修改,以及如何对其进行重构以使其正常工作?

我相信在Python中的线程之间共享变量的详细信息可以在中找到


本质上,在线程之间共享任何状态(包括变量)都需要同步(例如,使用
threading.Condition
)。否则,您将面临一个或多个线程之间竞争变量访问权的风险。

我相信在Python中,您可以在中找到在线程之间共享变量的详细信息


本质上,在线程之间共享任何状态(包括变量)都需要同步(例如,使用
threading.Condition
)。否则,您将面临一个或多个线程之间竞争访问变量的风险。

当您导入名称
has\u run
时,您已经在当前模块中创建了一个名为
has\u run
的新全局变量,它引用了与
文件1相同的对象。has\u run
,但对其中一个名称的赋值不会影响另一个名称。如果要查看
处理功能所做的更改
,则需要继续通过模块访问名称

while True:
    print(file1.has_run)
    ...
(这是因为
processing_函数
将一个新值分配给其全局值,而不是改变现有值。)

您可以通过一个更简单的示例来观察这一点。考虑一个非常简单的模块<代码> TMP1 < /代码>:

x = 3
现在了解如何从tmp1导入x创建一个全局变量,该变量的值保持独立于tmp1.x

>>> import tmp1
>>> from tmp1 import x
>>> x
3
>>> tmp1.x
3
>>> x = 6
>>> tmp1.x
3
>>> tmp1.x = 5
>>> tmp1.x
5
>>> x
6
>>>

导入名称
has\u run
时,您已在名为
has\u run
的当前模块中创建了一个新的全局文件,该文件引用了与
文件1.has\u run
相同的对象,但对其中一个名称的赋值不会影响另一个名称。如果要查看
处理功能所做的更改
,则需要继续通过模块访问名称

while True:
    print(file1.has_run)
    ...
(这是因为
processing_函数
将一个新值分配给其全局值,而不是改变现有值。)

您可以通过一个更简单的示例来观察这一点。考虑一个非常简单的模块<代码> TMP1 < /代码>:

x = 3
现在了解如何从tmp1导入x创建一个全局变量,该变量的值保持独立于tmp1.x:

>>> import tmp1
>>> from tmp1 import x
>>> x
3
>>> tmp1.x
3
>>> x = 6
>>> tmp1.x
3
>>> tmp1.x = 5
>>> tmp1.x
5
>>> x
6
>>>

可能存在微妙的竞争条件,但您可以在根本不使用线程的情况下重现问题(范围)。可能存在微妙的竞争条件,但您可以重现问题(范围)根本不使用线程。似乎还需要一个
锁来控制对全局变量的并发访问。是的,但我想让这个答案严格关注范围问题。比赛条件实际上是一个单独的问题。@chepner谢谢,它起作用了。我将file2中的import语句更改为just
import file1
,并根据您的回答更改了通过dots访问的两个位置。当我继续在代码的其余部分实现它时,我会思考一下为什么这样做有效,但是你的“分离”论点听起来直觉上是正确的。切普纳:你也完全掩盖了一个事实,即你在回答中所说的“分离”只适用于不可变的对象。例如,如果变量是一个
列表
,则无需通过其模块名引用它。换言之,我认为你可能对你的答案太“沉默”了。@martineau对于作业来说,这并不重要;名称
tmp1.x
x
完全不同,对其中一个的赋值不会影响对另一个的赋值。由于名称最初指的是同一个对象(我应该编辑我的答案以强调这一点),因此该对象的突变结果将通过任一名称可见。似乎还需要一个
锁来控制对全局变量的并发访问。True,但是我想让这个答案严格地集中在范围问题上。比赛条件实际上是一个单独的问题。@chepner谢谢,它起作用了。我将file2中的import语句更改为just
import file1
,并根据您的回答更改了通过dots访问的两个位置。当我继续在代码的其余部分实现它时,我会思考一下为什么这样做有效,但是你的“分离”论点听起来直觉上是正确的。切普纳:你也完全掩盖了一个事实,即你在回答中所说的“分离”只适用于不可变的对象。例如,如果变量是一个
列表
,则无需通过其模块名引用它。换言之,我认为你可能对你的答案太“沉默”了。@martineau对于作业来说,这并不重要;名称
tmp1.x
x
完全不同,对其中一个的赋值不会影响对另一个的赋值。由于名称最初指的是同一个对象(我应该编辑我的答案以强调这一点),因此该对象的变异结果将通过任一名称可见。