如何将写入文件的数据流式传输到标准输出
How to stream data written to file to stdout
我用 C 实现了共享库,它提供了一个函数 F
。每次我调用 F
时,它都会将其输出记录在文件 error.log
.
中
现在我正在尝试从 python 脚本中捕获 F
生成的输出(我正在使用 python 2.7.5,由于某些原因我无法更改我无法控制)。
我想将写入 error.log
的数据流式传输到不同的文件或 stdout
。我不能只打开文件并解析它,因为它登录了更多内容,包括 F
之前和之后运行的输出。我只对我无法从日志中识别的特定执行感兴趣。这就是我尝试捕获输出的原因。
我尝试从 python 打开 error.log
然后更改文件描述符使其指向 stdout
,但这似乎不起作用(我尝试了相同的stdout
和 stderr
确实有效)。
我做的大致是
with open('error.log') as logfile:
with redirect_output(logfile, sys.stdout):
function_implemented_in_C()
其中 redirect_output
是我实现的用于重定向的上下文管理器:
@contextmanager
def redirect_output(orig, dest):
orig_fd = orig.fileno()
with os.fdopen(os.dup(orig_fd)) as old_orig_fd:
os.dup2(dest.fileno(), orig_fd)
try:
yield orig
finally:
# clean and restore fd's
我无法让它工作。知道我做错了什么吗?
更新:
我将问题简化为一个简单的脚本,但它似乎仍然不起作用。我想这与从共享库 (?) 中的函数生成的数据有关,因为如果我这样做但重定向 write
从从 python 打开的文件的调用,它就可以工作。这个例子工作正常:
import sys
import os
def foo():
f = open('dummy.txt', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
f.write('some test data\n')
f.close()
if __name__ == '__main__':
foo()
但这不是
import sys
import os
def foo():
f = open('error.log', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
function_implemented_in_C()
f.close()
if __name__ == '__main__':
foo()
我正在回答我自己的问题,以防有人遇到同样的问题。
这里的问题是在 error.log
中产生输出的 C 函数启动了一个不同的进程来执行任务。这使得无法轻松地将对文件的写入重定向到 stdout
,因为文件描述符是特定于进程的。
因此,如果您的函数恰好使用相同的过程生成输出,那么以下应该有效
import sys
import os
def foo():
f = open('dummy.txt', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
f.write('some test data\n')
f.close()
if __name__ == '__main__':
foo()
如果不是这种情况,那么您可以通过设置从文件读取的循环来解决问题,以便它获取新写入的数据。类似的东西(我没有尝试过这段代码所以它不能 运行):
from multiprocessing import Process, Pipe
def foo(filename, pipe_conn):
with open(filename) as f:
while True:
line = f.readline()
do_something(line)
if pipe_conn.poll(0.01):
break
def bar(pipe_conn):
function_implemented_in_C()
pipe_conn.send(['done'])
pipe_conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=bar, args=(child_conn,))
p.start()
foo(parent_conn)
p.join()
我用 C 实现了共享库,它提供了一个函数 F
。每次我调用 F
时,它都会将其输出记录在文件 error.log
.
现在我正在尝试从 python 脚本中捕获 F
生成的输出(我正在使用 python 2.7.5,由于某些原因我无法更改我无法控制)。
我想将写入 error.log
的数据流式传输到不同的文件或 stdout
。我不能只打开文件并解析它,因为它登录了更多内容,包括 F
之前和之后运行的输出。我只对我无法从日志中识别的特定执行感兴趣。这就是我尝试捕获输出的原因。
我尝试从 python 打开 error.log
然后更改文件描述符使其指向 stdout
,但这似乎不起作用(我尝试了相同的stdout
和 stderr
确实有效)。
我做的大致是
with open('error.log') as logfile:
with redirect_output(logfile, sys.stdout):
function_implemented_in_C()
其中 redirect_output
是我实现的用于重定向的上下文管理器:
@contextmanager
def redirect_output(orig, dest):
orig_fd = orig.fileno()
with os.fdopen(os.dup(orig_fd)) as old_orig_fd:
os.dup2(dest.fileno(), orig_fd)
try:
yield orig
finally:
# clean and restore fd's
我无法让它工作。知道我做错了什么吗?
更新:
我将问题简化为一个简单的脚本,但它似乎仍然不起作用。我想这与从共享库 (?) 中的函数生成的数据有关,因为如果我这样做但重定向 write
从从 python 打开的文件的调用,它就可以工作。这个例子工作正常:
import sys
import os
def foo():
f = open('dummy.txt', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
f.write('some test data\n')
f.close()
if __name__ == '__main__':
foo()
但这不是
import sys
import os
def foo():
f = open('error.log', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
function_implemented_in_C()
f.close()
if __name__ == '__main__':
foo()
我正在回答我自己的问题,以防有人遇到同样的问题。
这里的问题是在 error.log
中产生输出的 C 函数启动了一个不同的进程来执行任务。这使得无法轻松地将对文件的写入重定向到 stdout
,因为文件描述符是特定于进程的。
因此,如果您的函数恰好使用相同的过程生成输出,那么以下应该有效
import sys
import os
def foo():
f = open('dummy.txt', 'wb', buffering=0)
os.dup2(sys.stdout.fileno(), f.fileno())
f.write('some test data\n')
f.close()
if __name__ == '__main__':
foo()
如果不是这种情况,那么您可以通过设置从文件读取的循环来解决问题,以便它获取新写入的数据。类似的东西(我没有尝试过这段代码所以它不能 运行):
from multiprocessing import Process, Pipe
def foo(filename, pipe_conn):
with open(filename) as f:
while True:
line = f.readline()
do_something(line)
if pipe_conn.poll(0.01):
break
def bar(pipe_conn):
function_implemented_in_C()
pipe_conn.send(['done'])
pipe_conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=bar, args=(child_conn,))
p.start()
foo(parent_conn)
p.join()