2015-12-02 292 views
1

我正在Python中編寫一個bot,並「人性化」它,我需要隨機暫停和恢復函數。 只能在某些定義的點處暫停和恢復功能。暫停和恢復功能

殭屍製成的各種功能,如

do_action1(*args) 
do_action2(*args) 
do_action3(*args) 
... 
start_bot() 
stop_bot() 

功能start_bot()調用do_action1()do_action2(),...爲了和給他們*args
我需要找到一種方法來隨機啓動do_actionX()功能,在某些點暫停並運行另一個隨機do_actionX()函數,那麼暫停和恢復前一個等等...

要隨機啓動的功能我我以爲我可以使用裏面有函數的字典並隨機選擇其中的一個。

我想我可以用線程做到這一點,但由於我的機器人正在使用多處理,它會是一個正確的選擇使用多線程和多處理?
我使用多處理器同時運行多個機器人,並通過鏈接到接口的主Python腳本來管理它們。每個bot實例都連接到一個不同的帳戶。

如果我使用多線程,我該如何使函數停止在某些定義點而不是隨機?

例如:

def do_action1(*args): 
    print("something") 
    # do something else 
    # <--- at this point the function could be paused 
    print("something") 
    # <--- at this pint the function cannot be paused! 
    print("else") 
    # <--- and here the function could be paused again 

的倍的功能將被暫停必須是隨機的。有沒有辦法做到這一點?
線程是否正確解決此問題?

+3

爲什麼不使用函數內部的yield來暫停?如果沒有其他功能需要運行,請調用相同的功能。這將使它成爲每個機器人的一個線程 – user1827356

+1

請參閱[關於協程和併發的好奇課程](http://www.dabeaz.com/coroutines/) –

回答

3

您可以使用yield關鍵字來創建協同例程。這裏有一個例子:

import random 
random.seed() 

def do_action1(): 
    print("Hello") 
    yield 
    print("HELLO!") 
    yield 
    print("hello?") 
def do_action2(): 
    print("Are you there?") 
    yield 
    print("ARE YOU THERE!") 
    yield 
    print("I'm scared.") 
def do_action3(): 
    print("Is somebody out there?") 
    yield 
    print("SOMEBODY IS OUT THERE!") 
    yield 
    print("I'm dead.") 

def bot(*actions): 
    actions = [action() for action in actions] 
    while actions: 
     action = random.choice(actions) 
     try: 
      next(action) 
     except StopIteration: 
      actions.remove(action) 
    return 

bot(do_action1, do_action2, do_action3) 
+0

謝謝。我會盡力實現你的代碼:) – GroovyTony

0

線程是一個好辦法。要暫停功能,使用time.sleep()(基於How can I make a time delay in Python?):

import time, random 

# Time range to sleep, in seconds 
def randomWait(): 
    sleepMin = 1.0 
    sleepMax = 5.0 
    time.sleep(random.uniform(sleepMin, sleepMax)) 

def do_action1(*args): 
    print("something") 
    # do something else 
    randomWait() 
    print("something") 
    print("else") 
    randomWait() 

我在這個例子中使用random.uniform,但你可以自由地進行時間間隔爲花哨的隨機性,你想使用random模塊或任何你喜歡的東西。

線程化解決方案將允許不同的操作同時運行。如果你不想讓這種情況,使用一個單獨的線程,並使用yield爲user1827356提示:

import time, random 

# Time range to sleep, in seconds 
def randomWait(): 
    sleepMin = 1.0 
    sleepMax = 5.0 
    time.sleep(random.uniform(sleepMin, sleepMax)) 

def do_action1(*args): 
    print("something") 
    # do something else 
    yield 
    print("something") 
    print("else") 

# Other actions defined similarly 

actions = [do_action1(), do_action2(), do_action3()] 
while actions: 
    randomWait() 
    action = random.choice(actions) 
    try: 
     next(action) 
    except StopIteration: 
     actions.remove(action) 

注意,在這種情況下,你的行爲是發電機。它們基本上是運行您定義的代碼並存儲狀態(暫停)的對象,只要它們碰到yield關鍵字。對於單線程應用程序,這可能是最好的方法。

+0

您尚未正確複製@Robᵩ的答案。你不會調用這些動作,所以他們永遠不會達到第一個「收益」。 –

+0

感謝您的收穫。我沒有複製羅布,雖然他確實首先發布了這個部分。我的回答在編輯之前有StopIteration捕獲。 –