2015-12-02 2 views
1

Я пишу бота на питоне и «очеловечиваю» его Мне нужно приостановить и возобновить функции случайным образом. Функции могут быть приостановлены и возобновлены только в некоторых определенных точках.Пауза и возобновление функции

бот сделан из различных функций, как

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, связанного с интерфейсом. Каждый экземпляр бота подключается к другой учетной записи.

Если я использую многопоточность, как я могу заставить функцию останавливаться в определенных точках, а не беспорядочно?

Например:

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

Почему бы не использовать выход внутри функции для паузы? И вспомните ту же функцию, если не нужно запускать другую функцию. Это сделало бы одну нить за бот – 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, прежде чем он был отредактирован. –

Смежные вопросы