簡體   English   中英

Python多線程問題

[英]Python multithreading issue

碼:

#!/usr/bin/env python

import os
import sys
import threading

class fifo_buffer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.dict_buffer = {}

    def run(self):
        path =  "/media/ramdisk/sample.fifo"
        fifo = open(path, "r")
        count = 0
        for line in fifo:
            count = count + 1
            self.dict_buffer[count] = line
            #print str(count) + " -> " + self.dict_buffer[count]
        fifo.close()

    def get_packet(self, index):
        return self.dict_buffer[index]

    def len_dict(self):
        print "Length dict: " + str(len(self.dict_buffer))

def main():
   fb = fifo_buffer()
   fb.start()
   print "get_packet(2): " + fb.get_packet(2)   # Input Error
   fb.len_dict()                                # Length showing zero

if __name__ == "__main__":
   main()
  1. 運行功能:

    我正在嘗試從fifo文件讀取並將數據存儲到字典中。 此運行功能幾乎無限執行。

  2. get_packet或len_dict函數:

    我正在嘗試獲取字典的詳細信息,但無法獲取。

我的疑問是運行功能何時將數據從fifo文件存儲到字典中,而假定使用get_packet或len_dict無限進行,我想訪問此字典數據結構,但無法訪問它

我是線程技術的新手,因此也歡迎使用任何其他方法。

我認為問題可能是您沒有弄清楚多個線程是如何工作的。 調用fb.start() ,兩個線程(從fifo文件讀取並將數據存儲到字典中的主線程和run()線程)同時工作。

您在調用print "get_packet(2): " + fb.get_packet(2)時遇到的get_packet(2)是因為當主線程調用get_packet(2)run()線程尚未將數據追加到字典中。

因此,只有在調用join()之后,才能訪問字典數據?

不完全是。 請繼續閱讀。

在run()線程無限執行時,它們有什么方法可以訪問字典?

你可以處理/訪問字典中run() thread同時run() thread正在執行,但很明顯,隨着時間的推移這本詞典的變化,你只能訪問行run() thread已經處理。 您還可以在run() thread 線程時在主線程中處理/訪問字典,但是正如我之前所說, run() thread可能沒有將數據追加到字典中(您只能訪問run() thread也已經處理過)。

我已經測試了代碼,添加了新方法並進行了一些修改。 運行良好。 修改后的代碼如下。

#!/usr/bin/env python

import os
import sys
import threading

class fifo_buffer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.dict_buffer = {}

    def run(self):
        print("run() starts.")
        path = "./sample.fifo"
        fifo = open(path, "r")
        count = 0
        for line in fifo:
            count = count + 1
            self.dict_buffer[count] = line
            print("in for expression: before show_dict()")
            self.show_dict()    # you could process dict_buffer here, but obviously this dict changes over time, and you could only access the lines that run() thread has already processed.
            #print str(count) + " -> " + self.dict_buffer[count]
        fifo.close()
        print("run() completes.")

    def get_packet(self, index):
        return self.dict_buffer[index]

    def len_dict(self):
        print("Length dict: " + str(len(self.dict_buffer)))

    def show_dict(self):
        print(self.dict_buffer)

def main():
   fb = fifo_buffer()
   fb.start()
   # fb.join()
   # print("get_packet(2): " + fb.get_packet(2))
   # you could process dict_buffer here, but you could only process/access the lines which run() thread has already processed.
   fb.len_dict()
   fb.show_dict()

if __name__ == "__main__":
   main()

正如我在我的評論說一個,這個例子中(尤其是main功能) 並不能使從多線程的POV多大意義。 這是對代碼“ 稍微 ”修改的:

#!/usr/bin/env python

import os
import sys
import threading


class FifoBufferThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.dict_buffer = {}

    def run(self):
        print("Begin inner thread run...")
        path = "/media/ramdisk/sample.fifo"
        count = 0
        with open(path, "r") as fifo:
            for line in fifo:
                count += 1
                self.dict_buffer[count] = line
                #print str(count) + " -> " + self.dict_buffer[count]
        print("End inner thread run")

    def get_packet(self, index):
        return self.dict_buffer.get(index, None)

    def get_dict_len(self):
        return len(self.dict_buffer)

    def len_dict(self):
        print "Length dict: " + str(self.get_dict_len())


def main():
    print("Main thread starting...")
    fbt = FifoBufferThread()
    fbt.daemon = True
    fbt.start()
    user_selection = None
    while True:
        user_selection = raw_input("Press any key to continue, 'x' (lowercase) to exit: ")
        if user_selection == "x":
            print("Exiting at user's choice.")
            break
        print(fbt.len_dict())
        # Do whatever else you might think is necessary with the dict
    print("Exiting")


if __name__ == "__main__":
    main()

現在,可以看到線程與inner( FifoBufferThread )線程進行交互。

變化

  • main函數現在是一個循環( 啟動fbt線程之后),以更好地說明該線程在后台執行的操作(以及fbt如何影響主線程)。 它涉及用戶交互(需要按下一個鍵),如果該鍵是小寫的x ,則程序將退出。
    重要說明 :程序等待用戶輸入時,內部線程將繼續執行其工作 ,因此它將從文件中讀取行
  • 重要的一個! fbt.daemon = True :該線程被標記為守護程序 [Python]:線程對象指出:

    線程可以標記為“守護程序線程”。 該標志的重要性在於,僅保留守護程序線程時,整個Python程序都會退出。

  • get_packet :我將其修改為使用[Python]:dict.get (並返回None而不是引發異常並終止程序)
  • 添加了get_dict_len函數(現在由len_dict )。 最好先獲取數據,然后再格式化以用於打印
  • 我不確定文件的讀取速率,還是其他程序寫入文件的速率,也不確定其初始內容,但是會發生以下情況之一( 假設一旦打開文件即可讀取文件,將在其他進程寫入內容時“更新”其內容):

    1. 您的應用程序將“吃掉”文件中的所有內容,最終到達EOF ,線程將停止(正常情況)
    2. TCP讀取的另一個應用程序將寫得足夠快(不太可能),因此讀取文件內容(並將其存儲在dict: IN MEMORY中 )的應用程序最終將耗盡內存

      2.1。 一種味道: RAM不會用完,但是磁盤( / media )會用完

  • 注意:還有更多可以改進的地方

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM