Python 创建一个进程,该进程创建一个线程,该线程再次更新一个全局变量

Python 创建一个进程,该进程创建一个线程,该线程再次更新一个全局变量,python,python-3.x,multithreading,multiprocessing,Python,Python 3.x,Multithreading,Multiprocessing,目前,我正在尝试在Python程序中生成一个进程,该程序再次创建线程,不断更新进程地址空间中的变量。到目前为止,我提出了这段运行的代码,但是变量的更新似乎没有传播到流程级别。我本以为在进程地址空间中定义变量并在线程中使用global(它共享进程的地址空间)将允许线程操作变量并将更改传播到进程 下面是该问题的一个最小示例: import multiprocessing import threading import time import random def process1():

目前,我正在尝试在Python程序中生成一个进程,该程序再次创建线程,不断更新进程地址空间中的变量。到目前为止,我提出了这段运行的代码,但是变量的更新似乎没有传播到流程级别。我本以为在进程地址空间中定义变量并在线程中使用global(它共享进程的地址空间)将允许线程操作变量并将更改传播到进程

下面是该问题的一个最小示例:

import multiprocessing 
import threading
import time
import random

def process1():
    lst = {}
    url = "url"
    thrd = threading.Thread(target = urlCaller, args = (url,))
    print("process alive")
    thrd.start()

    while True:
        # the process does some CPU intense calculation
        print(lst)
        time.sleep(2)

def urlCaller(url):
    global lst

    while True:
        # the thread continuously pulls data from an API
        # this is I/O heavy and therefore done by a thread
        lst = {random.randint(1,9), random.randint(20,30)}
        print(lst)
        time.sleep(2)


prcss = multiprocessing.Process(target = process1)
prcss.start()
进程总是打印一个空列表,而线程按照预期打印一个包含两个整数的列表。我希望这个过程也会打印一个包含两个整数的列表。 (注意:我使用Spyder作为IDE,如果我在Linux/Ubuntu上运行此代码,控制台上只会打印一些内容,但如果我在Windows上运行完全相同的Spyder代码,控制台上不会打印任何内容。)

我知道使用全局变量并不总是一个好的解决方案,但我认为在这种情况下它很好地达到了目的


您可能想知道我为什么要在进程中创建线程。基本上,我需要在不断变化的不同数据集上运行相同的复杂计算。因此,我需要多个进程(每个数据集一个进程)来优化CPU的利用率,并在进程内使用线程以使I/O进程最高效。数据贬值非常快,因此,我不能仅仅将其存储在数据库或文件中,这当然会简化数据生产者(线程)和数据消费者(进程)之间的通信过程。

您正在函数
process1
中定义一个局部变量
lst
,因此,
urlCaller
所做的与此无关,它不能更改不同函数的局部变量
urlCaller
正在定义一个全局变量,但是
process1
永远看不到它,因为它被您定义的局部变量所隐藏

您需要从该函数中删除
lst={}
,并找到其他方法返回值或在那里声明变量
global

def process1():
    global lst
    lst = {}
    url = "url"
    thrd = threading.Thread(target = urlCaller, args = (url,))
    print("process alive")
    thrd.start()

    while True:
        # the process does some CPU intense calculation
        print(lst)
        time.sleep(2)

我会使用类似于
concurrent.futures
的东西,而不是直接使用
threading
模块

多亏了前面的答案,我发现最好实现一个进程类并在这个类中定义“线程函数”。现在,线程可以访问共享变量并操作该变量,而无需使用“thread.join()”和终止线程

下面是两个并发线程为父进程提供数据的最小示例

import multiprocessing
import threading
import time
import random

class process1(multiprocessing.Process):
    lst = {}
    url = "url"

    def __init__(self, url):
        super(process1, self).__init__()
        self.url = url

    def urlCallerInt(self, url):
        while True:
            self.lst = {random.randint(1,9), random.randint(20,30)}
            time.sleep(2)

    def urlCallerABC(self, url):
        while True:
            self.lst = {"Ab", "cD"}
            time.sleep(5)

    def run(self):
        t1 = threading.Thread(target = self.urlCallerInt, args=(self.url,))
        t2 = threading.Thread(target = self.urlCallerABC, args=(self.url,))
        t1.start()
        t2.start()

        while True:
            print(self.lst)
            time.sleep(1)

p1 = process1("url")
p1.start()

巴库里亚,非常感谢!变量的正确范围起到了作用。我现在不再使用两个函数,而是创建一个拥有函数的进程类,然后在线程中调用这些函数。