【问题标题】:Pause and resume a function暂停和恢复功能
【发布时间】:2015-12-02 20:27:57
【问题描述】:

我正在用 python 编写一个机器人,为了“人性化”它,我需要随机暂停和恢复功能。 功能只能在某些定义的点暂停和恢复。

机器人由各种功能组成,例如

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

函数暂停的时间必须是随机的。有没有办法做到这一点?
线程是解决这个问题的正确方法吗?

【问题讨论】:

标签: python multithreading random artificial-intelligence


【解决方案1】:

您可以使用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)

【讨论】:

    【解决方案2】:

    线程是一种很好的方法。要暂停该功能,请使用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 关键字时存储状态(暂停)的对象。对于单线程应用程序,这可能是最好的方法。

    【讨论】:

    • 您没有正确复制@Robᵩ的答案。您没有调用这些操作,因此它们永远不会到达第一个 yield
    • 感谢您的收获。尽管他确实先发布了那部分,但我没有复制 Rob。我的答案在他被编辑之前就被 StopIteration 捕获了。
    猜你喜欢
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多