2017-06-16 43 views
1

我寫了一個我的問題的示例代碼。輸入消息被分成固定塊,並使用有意的隨機延遲進行混合。但是,sleep()正在阻止並且不會運行下一個任務。這是可能的單線程還是我不得不求助於多線程?如何在python中觸發異步非阻塞調度任務或事件?

from random import randint 
from time import sleep 

def delay_message(split_message, delay): 
    #sleep(delay) #this blocks 
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main(): 
    message = raw_input('Input: ') 

    #padding 
    difference = len(message) % 5 
    message=message.ljust(len(message)+5-difference, "0") 

    for i in range(0, len(message), 5): 
     delay = randint(0, 5) 
     split_message = message[i:i+5] 
     delay_message(split_message, delay) 

if __name__ == "__main__": 
    main() 
+0

查看['asyncio'](https://docs.python.org/3/library/asyncio.html)。如果它真的只是你需要的非阻塞睡眠,那可能會有所幫助。 –

回答

1

sleep確實會阻止其正在運行的線程。

可以通過使用庫如gevent使其非阻塞。 Gevent還可以修補time.sleep並使其非阻塞,並且還具有其自身的非阻塞睡眠。它也可以修補整個python標準庫,使其無阻塞 - 套接字,時間,線程等,請參閱documentation

上面的例子可以由具有GEVENT共同可操作併發像這樣:

from random import randint 
from gevent import sleep, spawn, joinall 

def delay_message(split_message, delay): 
    # Gevent's sleep yields the event loop for 
    # duration of delay rather than blocking the running thread 
    sleep(delay) 
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main(): 
    message = raw_input('Input: ') 

    #padding 
    difference = len(message) % 5 
    message=message.ljust(len(message)+5-difference, "0") 

    greenlets = [] 
    # This will create len(message)/5 number of greenlets, 
    # which corresponds to the concurrency level. 
    # Greenlets all run under one thread so there is no CPU 
    # overhead here. 
    for i in range(0, len(message), 5): 
     delay = randint(0, 5) 
     split_message = message[i:i+5] 
     greenlets.append(spawn(delay_message, split_message, delay)) 
    # Wait for all greenlets to complete, raise any exceptions 
    joinall(greenlets, raise_error=True) 

if __name__ == "__main__": 
    main() 

的約束是,CPU密集型任務不能在greenlets運行,因爲它們會阻止事件循環和所有其他greenlets。

只要在greenlet中運行的是I/O綁定,就像在套接字或生成器中傳遞消息一樣,其他greenlets等,greenlet也是適用的。對於CPU綁定的任務,請使用本機線程或多個進程。

還有其他的選擇,比如asyncio(僅Py3)。 Gevent與Py2和3兼容,並且具有非常高的性能,並由本機代碼擴展支持。

+0

謝謝,這很有趣。通過CPU綁定,你的意思是,如果delay_message執行繁重的操作?或者你可以給我一個例子,你的意思是這樣的 – Anderson

+0

CPU綁定任務將是在CPU上執行代碼時被阻塞的任何東西。例如音頻/視頻編碼和解碼,圖像處理等,基本上涉及在CPU上運行的代碼。 I/O綁定任務將通過網絡讀取/寫入流,網絡請求處理,磁盤I/O等。網絡也可以由線程來處理,但這意味着很多CPU開銷(CPU使用率增加,最大併發度降低)對於事實上並未受CPU限制的事情。爲此,合作多任務即異步I/O更適合。 – danny

+0

這是有道理的感謝。 Gevent沒有'usleep()或nanosleep()'高度的準確性。有沒有辦法處理這與當前的方法?或者你能否建議另一種方式,我可以研究 – Anderson