首页 > 解决方案 > 更新传递给线程python的变量

问题描述

我目前遇到的问题与我对线程的理解有关,或者可能是我对如何通过 python 中的线程传递/分配变量的理解。我有一个简单的程序,它接收显示在屏幕上的当前股票列表并获取与这些股票相关的股票信息。我正在使用线程,以便我可以不断更新屏幕并不断收集数据。我有两个问题:

  1. 在里面dataCollector_thread()我明白,如果我附加到里面stocksOnScreenListInfo的变量(stocksOnScreenListInfomain被更新。

但是我不想附加到列表中,而只是像下面这样重新分配列表,但这不起作用?

def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen):
    while(True):
        placeholder = []
        for stock in stocksOnScreen:
            placeholer.append(RetrieveQuote(stock))
        stocksOnScreenListInfo = placeholder
        time.sleep(5)
  1. 在里面screenUpdate_thread我想更新stocksOnScreen到函数定义的变量'TSLA' UpdateScreen。当我打印以检查它是否继续说“AAPL”时,这似乎没有更新其对应stocksOnScreen的内容?main

    def main(args): 
    
     stocksOnScreen = ["AAPL"] # List of the stocks currently displayed on LED screen
    
     stocksOnScreenListInfo = [] # The quote information list for each stock on screen 
    
     thread_data_collector = threading.Thread(target=dataCollector_thread, args=(stocksOnScreenListInfo,stocksOnScreen))
     thread_data_collector.daemon = True
     thread_data_collector.start()
    
     thread_screen = threading.Thread(target=screenUpdate_thread, args=(stocksSearchArray,stocksOnScreen))
     thread_screen.daemon = True
     thread_screen.start()
    
    
    
     def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen):
         while(True):
             for stock in stocksOnScreen:
                 stocksOnScreenListInfo.append(RetrieveQuote(stock))
             time.sleep(5)
    
     def screenUpdate_thread(stocksSearchArray, stocksOnScreen):
         while(True):
             stocksOnScreen = UpdateScreen(stocksSearchArray)
    
    
     def UpdateScreen(stocksSearchArray):
         pass
    
     return ["TSLA"]
    

标签: pythonpython-3.xmultithreadingpython-multithreading

解决方案


这个函数有几个问题:

def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen):
    while(True):
        placeholder = []
        for stock in stocksOnScreen:
            placeholer.append(RetrieveQuote(stock))
        stocksOnScreenListInfo = placeholder
        time.sleep(5)
  • stocksOnScreenListInfo在此函数中分配给一个新列表placeholder。您要做的是就地修改内容,以便stocksOnScreenListInfo更新main。您可以这样做:(stocksOnScreenListInfo[:] = placeholder这意味着使用新列表从头到尾更改内容)。

  • stocksOnScreen因为您在另一个线程中更新它,所以在 for 循环中迭代它时可能会发生变化。您应该以原子方式执行此操作。(作为 参数传递给函数)在这里会有所帮助:它是一种同步原语,旨在防止在多个线程共享数据并且其中至少一个线程修改它时发生数据竞争。

我看不到stocksOnScreenListInfo在您的代码中的其他任何地方使用。它是否用于其他功能?如果是这样,您应该考虑锁定它。

我会像这样修改函数:

def dataCollector_thread(stocksOnScreenListInfo, stocksOnScreen, lock):
    while True:
        placeholder = []
        with lock: # use lock to ensure you atomically access stocksOnScreen
            for stock in stocksOnScreen:
                placeholder.append(RetrieveQuote(stock))
        stocksOnScreenListInfo[:] = placeholder  # modify contents of stocksOnScreenListInfo
        time.sleep(5)

在您的其他线程函数中:

def screenUpdate_thread(stocksSearchArray, stocksOnScreen):
     while(True):
         stocksOnScreen = UpdateScreen(stocksSearchArray)

您正在分配stocksOnScreen给此函数中的新列表;它不会影响stocksOnScreenin main。同样,您可以使用符号来做到这一点stocksOnScreen[:] = new_list。我会在更新之前锁定,stocksOnScreen以确保您的其他线程函数像这样以原子方式dataCollector_thread访问:stocksOnScreen

def screenUpdate_thread(stocksSearchArray, stocksOnScreen, lock):
    while True:
        updated_list = UpdateScreen() # build new list - doesn't have to be atomic

        with lock:
            stocksOnScreen[:] = updated_list  # update contents of stocksOnScreen

        time.sleep(0.001)

如您所见,我进入了小睡眠状态,否则该函数将不断循环并且占用大量 CPU。另外,它会让 Python 有机会在线程函数之间进行上下文切换。

最后,在main创建一个锁:

lock = threading.Lock()

lock并作为参数传递给这两个函数。


推荐阅读