簡體   English   中英

Python線程與奇怪的輸出錯誤

[英]Python threading with strange output errors

我是新手一般的線程,並且一直在玩弄不同的想法讓我腳踏實地。 但是,我遇到了一些我不確定如何解釋的事情。 這是代碼:

import threading, datetime
class ThreadClass(threading.Thread):
    def run(self):
        for _ in range(3):
            now = datetime.datetime.now()
            print "%s: %s" %(self.getName(), now)

for i in range(2):
    t = ThreadClass()
    t.start()

該程序正是我想要它做的,但是,輸出中有一些隨機錯誤。

Thread-1: 2016-10-12 17:34:23.012462
Thread-1: 2016-10-12 17:34:23.012802
 Thread-2: 2016-10-12 17:34:23.013025
Thread-2: 2016-10-12 17:34:23.013108

Thread-2: 2016-10-12 17:34:23.013225
Thread-1: 2016-10-12 17:34:23.013252

錯誤是相對一致的(即輸出中顯示相同的空格和新行,只是在不同的地方)。 我懷疑它與幾乎同時寫入輸出流的線程有關,但是在這個特定的運行中,當Thread-2運行時會發生兩個錯誤。

任何幫助描述為什么會出現這個問題非常感謝!

我在Ubuntu 14.04(雙核CPU)上使用Python 2.7運行此代碼,如果這會有所不同。

作為Joseph回復的補充,你可以使用Semaphore

from threading import Semaphore
writeLock = Semaphore(value = 1)

...

當您要在線程中打印時:

writeLock.acquire()
print ("%s: %s" %(self.getName(), now))
writeLock.release()

writeLock確保在release()之前的任何一個時刻只能打印一個線程。

想象一下信號量是“蒼蠅之王”中的海螺,只有得到它的人才能說話。 當第一個發言者結束時,他將它交給下一個發言者。

您正在尋找記錄模塊:

15.7.9。 線程安全

日志記錄模塊旨在是線程安全的,無需客戶端進行任何特殊工作。 它通過使用線程鎖來實現這一點; 有一個鎖可以序列化對模塊共享數據的訪問,每個處理程序還會創建一個鎖,以序列化對其底層I / O的訪問。

這是一個例子:

FORMAT = '%(threadName)s %(asctime)s'
logging.basicConfig(format=FORMAT, level=logging.DEBUG) # "level" default is to only print WARN and above.
logger = logging.getLogger('MyThreadClass')
logger.debug('')

你的部分問題是為什么會發生這種情況? 這是一個很好的問題,因為你會在輸出中注意到有一個完全虛假的空間,這兩個線程都沒有真正嘗試打印

Thread-1: 2016-10-12 17:34:23.012802
 Thread-2: 2016-10-12 17:34:23.013025
^

那是怎么到達那里的? 沒有你的線程試圖打印它! 它是由於Python 2.x中的print語句實現軟間距的方式

例如......當你執行print 1,你會在stdout收到

1              # there is no space after that 1 yet!

然后后續print 2將導致插入空格以給出最終輸出:

1 2

發生的事情是print <something>,語句被編譯到字節碼操作PRINT_ITEM PRINT_ITEM的實現:

  • 檢查輸出流以查看此流的最后一個PRINT_ITEM將其標記為需要打印軟空間;
  • 如果是的話,打印一個“”;
  • 然后打印我們的項目並將流注釋為需要另一個軟空間。

還有另一個字節碼操作PRINT_NEWLINE ,它打印一個新行並清除流上的任何軟空間標記。

現在在您的代碼中,每個線程將執行以下操作:

print "%s: %s" %(self.getName(), now)

這被編譯為:

PRINT_ITEM          # print the top of the stack
PRINT_NEWLINE       # print a new line

因此,線程交互可能意味着:

  • Thread-1可以執行PRINT_ITEM並將流標記為需要下一個PRINT_ITEM的PRINT_ITEM ;
  • Thread-2可以開始PRINT_ITEM ,並且看到流需要一個軟空間;
  • Thread-1現在打印一個新行;
  • Thread-2現在打印該空間及其項目;

請注意,如果出現以下情況不會發生此錯

  • 你使用sys.stdout.write來執行輸出; 要么
  • 你使用的是具有不同io結構的Python 3.x.

暫無
暫無

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

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