首页 > 解决方案 > 如何在两个单独的脚本中导入共享变量?

问题描述

我有以下简化的python代码:

myproject
├── main.py
├── shared_var.py
└── utils.py

shared_var.py:

FOO = 'INIT'

实用程序.py

import time
from shared_var import FOO

def func_b():
    global FOO
    print('func_b initial FOO value: ', FOO)
    for i in range(10):
        FOO = str(i)
        print('func_b FOO value: ', FOO)
        time.sleep(1)

    FOO = 'DONE'
    print('func_b FOO value: ', FOO)

主要.py:

import time
from shared_var import FOO
from utils import func_b
import threading


def check_FOO_status():
    print('main current FOO: ', FOO)
    if FOO == 'DONE':
        return True
    else:
        return False

if __name__ == "__main__":
    print('main start FOO value: ', FOO)

    t = threading.Thread(target=func_b)
    t.start()

    running = True
    while running:
        if check_FOO_status():
            break
        time.sleep(3)

    print('main end FOO value: ', FOO)

这是我试图在我的应用程序中解决的问题的过度简化版本。基本上我想做的是:

  1. 在 main.py 中启动一个子线程,子线程会异步执行一个耗时的任务。
  2. 子线程更新全局变量FOO以在处理任务时跟踪进度。
  3. main 并没有被耗时任务阻塞,它产生一个子线程来完成这个任务后,它会继续完成一些其他任务。然后它不断检查全局变量FOO以查看子线程的进度。

但是,输出如下:

/usr/local/bin/python3.6 /Users/john/myproject/main.py
main start FOO value:  INIT
func_b initial FOO value:  INIT
func_b FOO value:  0
main current FOO:  INIT
func_b FOO value:  1
func_b FOO value:  2
main current FOO:  INIT
func_b FOO value:  3
func_b FOO value:  4
func_b FOO value:  5
main current FOO:  INIT
func_b FOO value:  6
func_b FOO value:  7
func_b FOO value:  8
main current FOO:  INIT
func_b FOO value:  9
func_b FOO value:  DONE
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
main current FOO:  INIT
...(infinite loop)

如您所见,显然全局变量有两个副本FOO。主线程和子线程不共享单个全局变量。我认为这是导入的问题,但在网上搜索后我找不到原因。

有什么建议么?

标签: pythonmultithreadingimportshared-variable

解决方案


而不是from shared_var import FOO只写 write import shared_var,并且在更改/读取此 FOO 变量时使用shared_var.FOO而不是 just FOO。在这种情况下,我们使用的事实是,如果某个模块之前已经导入,然后我们尝试再次导入它,python 不会再次导入它,但它只会为您提供对内存中已经存在的对象的引用。看起来这不适用于import from建筑,所以你需要使用import.

这是工作代码:

主文件

import time
import shared_var
from utils import func_b
import threading


def check_FOO_status():
    print('main current FOO: ', shared_var.FOO)
    if shared_var.FOO == 'DONE':
        return True
    else:
        return False

if __name__ == "__main__":
    print('main start FOO value: ', shared_var.FOO)

    t = threading.Thread(target=func_b)
    t.start()

    running = True
    while running:
        if check_FOO_status():
            break
        time.sleep(3)

    print('main end FOO value: ', shared_var.FOO)

实用程序.py

import time
import shared_var

def func_b():
    print('func_b initial FOO value: ', shared_var.FOO)
    for i in range(10):
        shared_var.FOO = str(i)
        print('func_b FOO value: ', shared_var.FOO)
        time.sleep(1)

    shared_var.FOO = 'DONE'
    print('func_b FOO value: ', shared_var.FOO)

及其输出:

main start FOO value:  INIT
func_b initial FOO value:  INIT
main current FOO:  INIT
func_b FOO value:  0
func_b FOO value:  1
func_b FOO value:  2
main current FOO:  2
func_b FOO value:  3
func_b FOO value:  4
func_b FOO value:  5
func_b FOO value:  6
main current FOO:  6
func_b FOO value:  7
func_b FOO value:  8
func_b FOO value:  9
main current FOO:  9
func_b FOO value:  DONE
main current FOO:  DONE
main end FOO value:  DONE

推荐阅读