相关文章推荐
小眼睛的大象  ·  快速表计算 - Tableau·  1 年前    · 
腼腆的沙发  ·  springboot学习(五十八) ...·  1 年前    · 
想发财的茴香  ·  7.106 ...·  2 年前    · 

Python。对于长期运行的进程,是Pass还是Sleep?

58 人关注

我正在编写一个队列处理应用程序,它使用线程来等待和响应要交付给应用程序的队列消息。 对于应用程序的主要部分,它只需要保持活跃。 对于这样的代码例子。

while True: while True: time.sleep(1)

哪种方式对系统的影响最小? 不做任何事情,但保持一个python应用程序运行的首选方式是什么?

2 个评论
正确的答案是根本不做轮询I/O。例如,请看select()调用,操作系统在那里睡觉,直到有东西可以读取。
就线程而言,它们正在使用阻塞的TCP连接来等待消息。 我所关心的只是主线程,它除了处理命令行选项、读取配置和启动线程外,什么都不做。
python
Gavin M. Roy
Gavin M. Roy
发布于 2009-02-10
7 个回答
Jay
Jay
发布于 2017-11-17
已采纳
0 人赞同

我想 time.sleep() 将减少系统的开销。使用 通过 将导致循环立即重新评估并占用CPU,而使用time.sleep将允许执行被暂时中止。

EDIT :为了证明这一点,如果你启动Python解释器并运行这个。

>>> while True:
...     pass

你可以看到Python立即开始占用90-100%的CPU,与之相比。

>>> import time 
>>> while True:
...     time.sleep(1)

在活动监视器上几乎没有记录(这里使用的是OS X,但每个平台都应该是一样的)。

谢谢,我就知道是这样的,但我一直在文件中看到的是通过。
哦,上帝!谢谢你的这个......测试?我甚至懒得做这个小测试,现在我知道为什么我的二线城市会消耗这么多CPU了。
while True: time.sleep(1000) haha!
tzot
tzot
发布于 2017-11-17
0 人赞同

为什么要睡觉?你不想睡觉,你想等着线程结束。

# store the threads you start in a your_threads list, then
for a_thread in your_threads:
    a_thread.join()

See: thread.join

不过,我并不指望线程能够完成。 这是一个不间断的过程。 这个逻辑还适用吗?
tzot
当然,这个逻辑仍然适用。你会避免浪费甚至是几个周期的 "循环 "睡眠。
这似乎不起作用,因为线程不应该终止进程,超时在概念上可能总是先出现,或者我错过了什么?
@Crad -- 什么超时? 主线程在永远地等待孩子。 这就是主线程的工作。
tzot
@Crad:在我的示例代码中,我没有指定任何超时,所以连接将永远等待。你有理由自己指定一个吗?
Matthew D. Scholefield
Matthew D. Scholefield
发布于 2017-11-17
0 人赞同

如果你正在寻找一种简短的、零CPU的方式来永远循环下去,直到一个KeyboardInterrupt,你可以使用。

from threading import Event
Event().wait()

Note: Due to 虫子,这只适用于Python 3.2以上的版本。此外,它似乎不能在 Windows 上工作。由于这个原因,while True: sleep(1)可能是更好的选择。

对于一些背景,Event对象通常用于等待长期运行的背景任务完成。

def do_task():
    sleep(10)
    print('Task complete.')
    event.set()
event = Event()
Thread(do_task).start()
event.wait()
print('Continuing...')

Which prints:

Task complete.
Continuing...
    
请注意,这在Linux和Mac上是可行的,但在Windows上,KeyboardInterrupt将 not 中断event.wait()。 如果指定了等待超时,异常将在超时结束时引发,但如果没有给出,那么event.wait()将永远阻塞。 在Windows上,一个SIGINT will 中断睡眠,所以这是更好的实现,在这里。 我没有在任何地方看到这个记录,但这是我在测试中的经验(Python 3.7)。我在这里找到了一个相关的主题。 stackoverflow.com/questions/39545612/...
@joshstaiger 有意思。我已经更新了帖子。我确实发现,由于Python 2中的一个bug,它不能工作,但我从来没有猜到它不能在Windows的3.2以上版本中工作。
@joshstaiger 很好的捕捉到了,找到了py-issue。 bugs.python.org/issue35935 .在查看松弛螺栓库时遇到了这个问题。 开始() func有一个针对windows的特殊情况;使用 signal.signal(signal.SIGINT, signal.SIG_DFL) 。不过不推荐这样做,因为SIGINT的默认动作是关闭整个python程序。while(1) sleep "的方法更好。
Adam
Adam
发布于 2017-11-17
0 人赞同

替换代码0】是另一种解决方案,见 https://docs.python.org/3/library/signal.html#signal.pause

导致进程睡眠,直到收到信号;然后调用适当的处理程序。不返回任何东西。在Windows上不适用。(参见Unix手册中的signal(2)。

你真的不应该这样做------它可能会导致线程中的问题。替换代码0】要好得多。
hernan43
hernan43
发布于 2017-11-17
0 人赞同

我总是看到/听说使用睡眠是更好的方法。使用睡眠可以使你的Python解释器的CPU使用率不至于太高。

Johan
Johan
发布于 2017-11-17
0 人赞同

你没有对你真正在做的事情给出很多背景,但也许 Queue 是否可以用 sleep 来代替明确的忙等待循环?如果没有,我认为 sleep 更合适,因为我相信它消耗的CPU更少(正如其他人已经指出的)。

[根据以下评论中的补充信息进行了编辑]。

也许这很明显,但无论如何,你的 could 在你从阻塞的套接字中读取信息的情况下,你可以让一个线程从套接字中读取信息,并将适当格式化的信息发布到 Queue 中,然后让其余的 "工作者 "线程从该队列中读取信息。然后,工人线程将在从队列中读取信息时进行阻塞,既不需要 pass ,也不需要 sleep

谢谢你关于队列的提示,在这个应用程序中,我使用阻塞套接字来监听来自AMQP代理的消息(在不同的线程中),并在收到后采取行动。
@Crad: 然后使用select来等待一个套接字,类似于队列的工作方式。 不要使用繁忙等待或轮询。
Ashish Gupta
Ashish Gupta
发布于 2017-11-17
0 人赞同

在Python中以睡眠方式运行一个方法作为后台线程

    import 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()