2017-08-10 38 views
0

我是新来的Python,请耐心等待我的问题。访问线程在不同模块中的本地对象 - Python

假设我的应用程序有一个名为message_printer的模块,它简单地定义了一个print_message函数来打印消息。现在在我的主文件中,我创建了两个线程,它们调用message_printer中的print函数。

我的问题是:如何为每个线程设置不同的消息并在message_printer中访问它?

message_printer:

import threading 

threadLocal = threading.local() 

def print_message(): 
    name = getattr(threadLocal, 'name', None); 
    print name 
    return 

主:

import threading 
import message_printer 

threadLocal = threading.local() 

class Executor (threading.Thread): 
    def __init__(self, name): 
     threading.Thread.__init__(self) 
     threadLocal.name = name 

    def run(self): 
     message_printer.print_message(); 

A = Executor("A"); 
A.start(); 
B = Executor("B"); 
B.start(); 

这只是输出NoneNone,而我希望AB。我也尝试直接访问print_message函数内的threadLocal对象,但不起作用。

请注意,这只是一个例子。在我的应用程序中,确切的用例是用于日志记录。主要启动一堆调用其他模块的线程。我想每个线程都有一个不同的记录器(每个线程都应该记录到它自己的文件中),并且每个记录器都需要在Main中配置。所以我试图实例化每个线程的记录器,并设置线程本地存储,然后可以在其他模块中访问。

我在做什么错?我以此问题为例Thread local storage in Python

回答

1

您的代码存在的问题是您没有将name指派给正确的local()上下文。您的__init__()方法在主线程中运行,然后通过调用.start()启动AB线程。

您的第一个线程创建A = Executor("A");将创建一个新线程A但更新主线程的本地上下文。然后,当您通过拨打A.start();开始A时,您将输入A:s上下文,并带有单独的本地上下文。这里没有定义name,并且最终以None作为输出。然后B发生。

换句话说,访问你应该运行当前线程,你运行.start()(这将调用.run()法)当线程局部变量,但创建的对象不是当(运行__init__())。

获得当前的代码的工作,你可以在数据存储中的每个对象(使用self引用),然后,每个线程运行时,复制内容到线程本地环境:

import threading 

threadLocal = threading.local() 

def print_message(): 
    name = getattr(threadLocal, 'name', None); 
    print name 
    return 

class Executor (threading.Thread): 
    def __init__(self, name): 
     threading.Thread.__init__(self) 
     # Store name in object using self reference 
     self.name = name 

    def run(self): 
     # Here we copy from object to local context, 
     # since the thread is running 
     threadLocal.name = self.name 
     print_message(); 

A = Executor("A") 
A.start() 
B = Executor("B") 
B.start() 

注尽管如此,在这种情况下,使用线程本地上下文有点矫枉过正,因为我们已经将不同的数据值存储在不同的对象中。要直接从对象中使用它,需要重写一次print_message()

+0

太棒了!在我的情况下,我需要访问存储在多个地方的不同模块中的本地线程中的对象。我想避免将它作为参数传递,所以看起来线程本地应该适合我的场景。 – RandomQuestion

相关问题