需要帮助将 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() 与 event.wait()