Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 无法正确读取标准数据_Python_Rsyslog - Fatal编程技术网

Python 无法正确读取标准数据

Python 无法正确读取标准数据,python,rsyslog,Python,Rsyslog,我在python脚本中读取STDIN时遇到了一个奇怪的问题 这是我的用例。我用输出模块配置了rsyslog,因此rsyslog可以将日志消息通过管道传输到我的Python脚本 我的Python脚本非常简单: #! /usr/bin/env python # -*- coding: utf-8 -*- import sys fd = open('/tmp/testrsyslogomoutput.txt', 'a') fd.write("Receiving log message : \n%s\n

我在python脚本中读取STDIN时遇到了一个奇怪的问题

这是我的用例。我用输出模块配置了rsyslog,因此rsyslog可以将日志消息通过管道传输到我的Python脚本

我的Python脚本非常简单:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys

fd = open('/tmp/testrsyslogomoutput.txt', 'a')
fd.write("Receiving log message : \n%s\n" % ('-'.join(sys.stdin.readlines())))
fd.close()
如果我运行echo“foo”| mypythonscript.py我可以在目标文件
/tmp/testrsyslogomoutput.txt
中获得“foo”。然而,当我在rsyslog中运行它时,似乎只有在我停止/重新启动rsyslog时才会发送消息(我相信某些缓冲区在某个点被刷新)

我首先认为这是Rsyslog的问题。因此,我用shell程序替换了python程序,而没有对rsyslog配置进行任何更改。shell脚本与rsyslog完美配合,正如您在下面的代码中所看到的,该脚本非常简单:

#! /bin/sh
cat /dev/stdin >> /tmp/testrsyslogomoutput.txt
由于我的shell脚本可以工作,但Python脚本不能工作,我相信我在Python代码中的某个地方犯了一个错误,但我找不到哪里。如果你能指出我的错误,那就太好了


提前感谢:)

读取行在完成文件读取之前不会返回。由于管道输送标准从未完成,
readlines
也从未完成。停止rsyslog将关闭管道并让其完成。

readlines
在完成文件读取之前不会返回。由于管道输送标准从未完成,
readlines
也从未完成。停止rsyslog将关闭管道并让其完成。

如果改用
readline()
,它将返回
\n
,但这只会写入一行,然后退出

如果您想保持书写行的长度,可以使用一个简单的
for

for line in fd:
  fd.write("Receiving log message : \n%s\n" % (line)
fd.close()
如果改用
readline()
,它将在
\n
上返回,尽管这只会写入一行,然后退出

如果您想保持书写行的长度,可以使用一个简单的
for

for line in fd:
  fd.write("Receiving log message : \n%s\n" % (line)
fd.close()

我还怀疑原因是rsyslog没有终止
readlines()
在达到实际EOF之前不应返回。但是为什么shell脚本的行为会有所不同呢?也许使用/dev/stdin就是原因。尝试此版本,看看它是否仍在不挂起的情况下运行:

#!/bin/sh
cat >> /tmp/testrsyslogomoutput.txt
如果这有所不同,您还将得到一个修复:从python打开并读取/dev/stdin,而不是sys.stdin

Edit:So
cat
以某种方式读取stdin中等待的内容并返回,但python会阻塞并等待stdin耗尽。奇怪。您也可以尝试将
readlines()
替换为一个
read()
,后跟
split(“\n”)
,但在这一点上,我怀疑这会有所帮助

因此,忘记诊断,让我们尝试一种解决方法:强制stdin执行非阻塞i/o。以下内容应该可以做到这一点:

import fcntl, os

# Add O_NONBLOCK to the stdin descriptor flags 
flags = fcntl.fcntl(0, fcntl.F_GETFL)
fcntl.fcntl(0, fcntl.F_SETFL, fl | os.O_NONBLOCK)

message = sys.stdin.read().split("\n")  # Read what's waiting, in one go
fd = open('/tmp/testrsyslogomoutput.txt', 'a')
fd.write("Receiving log message : \n%s\n" % ('-'.join(message)))
fd.close()

您可能希望将其与
python-u
结合使用。希望它能起作用

我还怀疑原因是rsyslog没有终止
readlines()
在达到实际EOF之前不应返回。但是为什么shell脚本的行为会有所不同呢?也许使用/dev/stdin就是原因。尝试此版本,看看它是否仍在不挂起的情况下运行:

#!/bin/sh
cat >> /tmp/testrsyslogomoutput.txt
如果这有所不同,您还将得到一个修复:从python打开并读取/dev/stdin,而不是sys.stdin

Edit:So
cat
以某种方式读取stdin中等待的内容并返回,但python会阻塞并等待stdin耗尽。奇怪。您也可以尝试将
readlines()
替换为一个
read()
,后跟
split(“\n”)
,但在这一点上,我怀疑这会有所帮助

因此,忘记诊断,让我们尝试一种解决方法:强制stdin执行非阻塞i/o。以下内容应该可以做到这一点:

import fcntl, os

# Add O_NONBLOCK to the stdin descriptor flags 
flags = fcntl.fcntl(0, fcntl.F_GETFL)
fcntl.fcntl(0, fcntl.F_SETFL, fl | os.O_NONBLOCK)

message = sys.stdin.read().split("\n")  # Read what's waiting, in one go
fd = open('/tmp/testrsyslogomoutput.txt', 'a')
fd.write("Receiving log message : \n%s\n" % ('-'.join(message)))
fd.close()

您可能希望将其与
python-u
结合使用。希望它能起作用

我试过了你的建议,没什么区别。它仍然可以完美地与这个微不足道的shell脚本配合使用。我还尝试在python脚本中读取/dev/stdin(没有readlines()),但它仍然挂起。下一个想法:通过调用带有-u标志的python,将python的i/o缓冲从等式中去掉。感谢您的支持Alexis,我也尝试了python-u,但它没有改变任何东西。看起来@abalus在Apache中遇到了类似的问题:我认为@abalus有相反的问题:在他的设置中,读取会立即返回,而不会阻塞,但是你的程序在cat返回时会阻塞,而不会阻塞。我尝试了你提出的方法,但没有任何区别。它仍然可以完美地与这个微不足道的shell脚本配合使用。我还尝试在python脚本中读取/dev/stdin(没有readlines()),但它仍然挂起。下一个想法:通过调用带有-u标志的python,将python的i/o缓冲从等式中去掉。感谢您的支持Alexis,我也尝试了python-u,但它没有改变任何东西。看起来@abalus在Apache中遇到了类似的问题:我认为@abalus有相反的问题:在他的设置中,读取会立即返回,而不会阻塞,但是你的程序在cat返回时会阻塞,而不会阻塞。我试过这个。问题依旧。我尝试在sys.stdin和/dev/stdin上循环,输入仅在发送时写入。使用上面建议的readline替代品也不起作用。我尝试了这个。问题依旧。我尝试在sys.stdin和/dev/stdin上循环,输入仅在发送时写入。如上所述,使用readline的替代方案也不起作用。