需要帮助将 time.sleep 与 python 3 中的多处理相结合

Posted

技术标签:

【中文标题】需要帮助将 time.sleep 与 python 3 中的多处理相结合【英文标题】:Need Help Combining time.sleep with multiprocessing in python 3 【发布时间】:2012-10-27 02:05:40 【问题描述】:

使用 python 3 制作回合制游戏。我想要 2 个角色(敌人和敌人)攻击,根据随机 + 速度暂停,如果他们还活着,则再次攻击。

我遇到的问题是 time.sleep 冻​​结了两个模块,而不是 1 或另一个。有什么建议可以有效地完成这项工作吗?

from multiprocessing import Process
import time
import random

def timing1():  
    speed=60#SPEED IS NORMALLY A KEY FROM LIST, USING 60 FOR EXAMPLE  
    sleeptime=36/((random.randint(1,20)+speed)/5)  
    print (sleeptime)  
    time.sleep(sleeptime)  
    input('HERO ACTION')  

def timing2():  
    speed=45  
    sleeptime=36/((random.randint(1,20)+speed)/5)  
    print (sleeptime)  
    time.sleep(sleeptime)  
    input('FOE ACTION')  

if __name__ == '__main__':  
    p1=Process(target=timing1)  
    p1.start()  
    p2=Process(target=timing2)  
    p2.start()  
    p1.join()  
    p2.join()

【问题讨论】:

【参考方案1】:

详细说明 J.F.

我对线程的一般建议是仅在绝对必要时才引入它。

您实际上是在低级 I/O 上阻塞,除了使用本机线程之外别无选择。 您正在达到计算限制,需要使用更多内核,在这种情况下,python 由于它的 GIL 可能对您不利。

作为替代方案,使用提供诸如 twisted 或 gevent 之类的调度程序的库,该库不依赖本机线程来调度事件。

gevent

您可以在编写游戏时考虑到线程模型,而不必担心线程之间的资源争用。 您必须记住在您的示例中使用 various functions 的 gevent 版本,例如 sleep

import random
import gevent


def hero():
    speed = 60
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    gevent.sleep(sleeptime)
    input('HERO ACTION')


def foe():
    speed = 45
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    gevent.sleep(sleeptime)
    input('FOE ACTION')


if __name__ == "__main__":
    heroThread = gevent.Greenlet(hero)
    foeThread = gevent.Greenlet(foe)

    heroThread.start()
    foeThread.start()

    gevent.joinall([heroThread, foeThread])

扭曲

提供一个事件反应器,它是用纯 python 编写的,并且不假装比单线程事件反应器(又名Event Loop)更多或更少。 这将需要对您的示例进行更大程度的重写。

import random
from twisted.internet import reactor


def heroAction():
    input('HERO ACTION')


def heroStart():
    speed = 60
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    reactor.callLater(sleeptime, heroAction)


def foeAction():
    input('FOE ACTION')


def foeStart():
    speed = 45
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    reactor.callLater(sleeptime, foeAction)


if __name__ == "__main__":
    # Call when the reactor has started.
    reactor.callWhenRunning(heroStart)
    reactor.callWhenRunning(foeStart)
    reactor.run()

请注意,扭曲反应堆在无事可做时不会关闭,这是明确留给程序员的。

自己动手

出于学习目的编写自己的调度程序可能会很有趣,或者您的游戏中可能有一些要求,例如需要它的公平性。 一个很好的起点是查看another minimalistic scheduler 以获得灵感。

【讨论】:

【参考方案2】:

转一圈后,进程会在您的代码中退出。您的主进程通过调用.join() 等待两个进程退出,即time.sleep() 不会冻结其他进程。

timing*() 函数顶部添加while True: 以进行多次移动。

这里不需要多个进程。您可以使用线程甚至单个线程来实现转弯。

【讨论】:

谢谢。这方面的新手,但要坚持下去。

以上是关于需要帮助将 time.sleep 与 python 3 中的多处理相结合的主要内容,如果未能解决你的问题,请参考以下文章

我需要python time.sleep()在C#中等效

Python time.sleep() 与 event.wait()

Python - time.sleep 的替代品

Python time.sleep 需要更长的时间

python中from time import sleep是啥意思

第五周-第05章节-Python3.5-内置模块详解之time与datetime模块