Python等待直到数据在sys.stdin中
我的问题是这样的:
我的Python脚本通过sys.stdin接收数据,但它需要等到sys.stdin上有新数据可用时才能继续。
根据Python的手册,我使用了以下代码,但这导致我的CPU完全被占满。
#!/usr/bin/python -u
import sys
while 1:
for line in sys.stdin.readlines():
do something useful
有没有什么好的方法来解决高CPU使用率的问题?
编辑:
你们的所有解决方案都不管用。我给你们说说我的具体问题。
你可以配置apache2守护进程,让它把每一行日志发送到一个程序,而不是写入日志文件。
这看起来像这样:
CustomLog "|/usr/bin/python -u /usr/local/bin/client.py" combined
Apache2希望我的脚本一直运行,等待sys.stdin上的数据,并在有数据时进行解析。
如果我只用一个for循环,脚本会退出,因为在某个时刻sys.stdin上没有数据,apache2就会说“哦,你的脚本意外退出了”。
如果我使用一个while true循环,我的脚本就会占用100%的CPU。
9 个回答
使用这个:
#!/usr/bin/python
import sys
for line in sys.stdin.readlines():
pass # do something useful
这个方法实际上运行得非常顺利(也就是说,没有CPU过载的问题)——当你从命令行调用这个脚本时,可以这样做:
tail -f input-file | yourscript.py
显然,这并不是最理想的做法——因为你需要把所有相关的输出写入那个文件中——
但这样做没有太多额外的负担!主要是因为使用了 readline()
,我觉得:
while 1:
line = sys.stdin.readline()
它会在那一行停下来,等待更多的输入。
希望这对某些人有帮助!
下面的代码应该可以正常工作。
import sys
for line in sys.stdin:
# whatever
解释一下:
这段代码会逐行读取输入流中的内容。当输入流还在打开状态,但没有完整的一行数据时,循环会一直等待,直到遇到换行符(这时会返回整行数据)或者输入流被关闭(这时会返回缓冲区中剩下的数据)。
一旦输入流关闭,就不能再往stdin写入或读取数据了。就是这么简单。
你代码让CPU过载的原因是,一旦stdin关闭,之后再尝试读取stdin时会立刻返回,不会执行任何操作。实际上,你的代码相当于下面的样子。
for line in sys.stdin:
# do something
while 1:
pass # infinite loop, very CPU intensive
也许你可以分享一下你是怎么往stdin写数据的,这样可能会更有帮助。
补充说明:
在Python中,对于for循环、迭代器和readlines()来说,当遇到EOF(文件结束符)时,流会被认为是关闭的。你可以让Python继续读取更多数据,但不能使用之前的方法。Python的手册建议使用
import sys
while True:
line = sys.stdin.readline()
# do something with line
当遇到EOF字符时,readline会返回一个空字符串。如果流仍然打开,下一次调用readline会正常工作。你可以在终端中运行这个命令来测试一下。按下ctrl+D会让终端向stdin写入EOF字符。这会导致这篇文章中的第一个程序终止,但最后一个程序会继续读取数据,直到流真正关闭。最后一个程序不会让你的CPU 100%占用,因为readline会等待有数据可返回,而不是返回空字符串。
我只有在从实际文件中调用readline时才会遇到忙碌循环的问题。但在从stdin读取时,readline会正常阻塞。