我正在编写一个队列处理应用程序,它使用线程来等待并响应要传递给应用程序的队列消息。 对于应用程序的主要部分,它只需要保持活动状态。 对于代码示例,例如:
1
2while True:
pass
要么
1
2while True:
time.sleep(1)
哪一个对系统的影响最小? 什么是什么都不做,但保持python应用程序运行?
正确的答案是根本不进行轮询I / O. 例如,请参阅select()调用,操作系统将在此处休眠,直到准备好读取内容为止。
好吧,在线程的情况下,他们使用阻塞TCP连接等待消息。 它只是我关注的主要线程,它除了处理命令行选项,读取配置和线程踢之外什么都不做。
我认为time.sleep()将减少系统的开销。使用pass将导致循环立即重新评估并固定CPU,而使用time.sleep将允许执行暂时中止。
编辑:只是为了证明这一点,如果你启动python解释器并运行:
1
2
3>>> while True:
... pass
...
您可以观看Python立即开始吃掉90-100%的CPU,而不是:
1
2
3
4>>> import time
>>> while True:
... time.sleep(1)
...
甚至几乎没有在Activity Monitor上注册(在这里使用OS X,但每个平台应该是相同的)。
谢谢,我认为就是这样,但我一直看到文件传递。
为什么睡觉?你不想睡觉,你想等待线程完成。
所以
1
2
3# store the threads you start in a your_threads list, then
for a_thread in your_threads:
a_thread.join()
请参阅:thread.join
不过,我不希望线程完成。这是一个没有结束的过程。这个逻辑是否仍然适用?
当然逻辑仍然适用。你可以避免浪费甚至几个周期来进行"循环"睡眠。
这似乎不起作用,因为线程不应该终止进程终止,超时可能在概念上总是先出现,或者我错过了什么?
@Crad - 什么超时?主要线索是永远等待孩子们。这就是主线程的作用。
@Crad:在我的示例代码中,我没有指定任何超时,因此连接将永远等待。你有理由自己指定一个吗?
如果您正在寻找一种简短的零CPU方式来循环直到KeyboardInterrupt,您可以使用:
1
2
3from threading import Event
Event().wait()
注意:由于存在错误,这仅适用于Python 3.2+。此外,它似乎无法在Windows上工作。因此,while True: sleep(1)可能是更好的选择。
对于某些背景,Event对象通常用于等待长时间运行的进程完成:
1
2
3
4
5
6
7
8
9
10def do_task():
sleep(10)
print('Task complete.')
event.set()
event = Event()
Thread(do_task).start()
event.wait()
print('Continuing...')
哪个印刷品:
1
2Task complete.
Continuing...
请注意,这适用于Linux和Mac,但在Windows上,KeyboardInterrupt不会中断event.wait()。如果指定了等待超时,则异常将在超时结束时引发,但如果没有给出,则event.wait()将永久阻塞。在Windows上,SIGINT将中断睡眠,这样就可以实现更好的实现。我在任何地方都没有看到这个,但它一直是我的测试经验(Python 3.7)。我在这里找到了一个相关的主题:stackoverflow.com/questions/39545612/
@joshstaiger有趣。我已经更新了帖子。我确实发现由于Python 2中的一个错误,它没有用,但我绝不会猜到它在Windows中无法使用3.2+。
你没有为你真正做的事情提供太多的背景,但是可能会使用Queue而不是显式的忙等待循环?如果没有,我会认为sleep会更好,因为我相信它会消耗更少的CPU(正如其他人已经注意到的那样)。
[根据以下评论中的其他信息进行编辑。]
也许这是显而易见的,但无论如何,在你从阻塞套接字读取信息的情况下,你可以做的是从套接字读取一个线程并将适当格式化的消息发布到Queue,然后让你剩下的"worker"线程从该队列中读取;然后,工作人员将阻止从队列中读取而不需要pass,也不需要sleep。
感谢Queue上的提示看起来很方便,在这个应用程序中,我使用阻塞套接字来侦听来自AMQP代理(在单独的线程中)的消息,并在收到时对它们采取行动。
@Crad:然后使用select在套接字上等待,类似于队列的工作方式。不要使用繁忙的等待或轮询。
我一直看到/听说使用睡眠是更好的方法。使用sleep将使您的Python解释器的CPU使用率不再过时。
signal.pause()是另一种解决方案,请参阅https://docs.python.org/3/library/signal.html#signal.pause
Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. Not on Windows. (See the Unix man page signal(2).)
在Python中使用sleep运行方法作为后台线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34import threading
import time
class ThreadingExample(object):
""" Threading example class
The run() method will be started and it will run in the background
until the application exits.
"""
def __init__(self, interval=1):
""" Constructor
:type interval: int
:param interval: Check interval, in seconds
"""
self.interval = interval
thread = threading.Thread(target=self.run, args=())
thread.daemon = True # Daemonize thread
thread.start() # Start the execution
def run(self):
""" Method that runs forever"""
while True:
# Do something
print('Doing something imporant in the background')
time.sleep(self.interval)
example = ThreadingExample()
time.sleep(3)
print('Checkpoint')
time.sleep(2)
print('Bye')