问题描述
我正在尝试等待一些文本写入 Python 中的实时日志文件.
I'm trying to wait until some text is written to a live logfile in Python.
fdpexect 似乎是解决此问题的正确方法,但它不是在等待.一旦到达文件末尾,它就会终止.
fdpexect would seem to be the right thing for this, but it isn't waiting. As soon as it hits the end of the file it terminates.
我想知道 fdpexpect 是否不支持这一点,我需要解决这个问题吗?
I'm wondering if fdpexpect just doesn't support this and I'll need to work around it?
我的代码基本上是这样的:
The code I have is basically this:
创建生成对象:
# we're not using pexpect.spawn because we want
# all the output to be written to the logfile in real time,
# which spawn doesn't seem to support.
p = subprocess.Popen(command,
shell=shell,
stdout=spawnedLog.getFileObj(),
stderr=subprocess.STDOUT)
# give fdspawn the same file object we gave Popen
return (p, pexpect.fdpexpect.fdspawn(spawnedLog.getFileObj()))
等待:
pexpectObj.expect('something')
这基本上会在发生 EOF 错误的某事"事件发生之前立即退出.
This basically quits immediately and before the 'something' event happens with an EOF error.
推荐答案
fdpexpect
不是为处理普通文件而设计的.pexpect
将始终从文件对象中读取,直到它遇到 EOF - 对于管道和套接字,这在连接实际关闭之前不会发生,但对于普通文件,它会在整个文件已被读取.它无法知道该文件正在被另一个进程主动写入.
fdpexpect
isn't design to work on normal files. pexpect
will always read from a file object until it hits EOF - for pipes and sockets, this won't happen until the connection is actually closed, but for normal files, it will happen as soon as the entire file has been read. It has no way of knowing that the file is actively being written to by another process.
您可以通过使用 os.pipe
创建管道来解决此问题,然后实现您自己的 tee
功能来编写 stdout
除了日志文件之外,您的进程到该管道.这是一个似乎有效的小玩具示例:
You could work around this by creating a pipe using os.pipe
, and then implementing your own tee
functionality to write the stdout
of your process to that pipe in addition to the log file. Here's a little toy example that seems to work:
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
import os
import pexpect.fdpexpect
# tee and teed_call are based on http://stackoverflow.com/a/4985080/2073595
def tee(infile, *files):
"""Print `infile` to `files` in a separate thread."""
def fanout(infile, *files):
for line in iter(infile.readline, ''):
for f in files:
f.write(line)
infile.close()
t = Thread(target=fanout, args=(infile,)+files)
t.daemon = True
t.start()
return t
def teed_call(cmd_args, files, **kwargs):
p = Popen(cmd_args,
stdout=PIPE,
stderr=STDOUT,
**kwargs)
threads = []
threads.append(tee(p.stdout, *files))
return (threads, p)
with open("log.txt", 'w') as logf:
# Create pipes for unbuffered reading and writing
rpipe, wpipe = os.pipe()
rpipe = os.fdopen(rpipe, 'r', 0)
wpipe = os.fdopen(wpipe, 'w', 0)
# Have pexpect read from the readable end of the pipe
pobj = pexpect.fdpexpect.fdspawn(rpipe)
# Call some script, and tee output to our log file and
# the writable end of the pipe.
threads, p = teed_call(["./myscript.sh"], [wpipe, logf])
# myscript.sh will print 'hey'
pobj.expect("hey")
# orderly shutdown/cleanup
for t in threads: t.join()
p.wait()
rpipe.close()
wpipe.close()
这篇关于我可以对当前正在写入的文件使用 fdpexpect 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!