问题描述
这主要是一个通用的python问题,我在分布式环境中工作,因此我的工作人员将其stdout和stderr写入共享文件系统上的文件中(我无法更改)。我希望启动器脚本读取其中一个文件并实时打印出来,以大致跟踪工作进程,每个进程都使用tqdm输出进度条。我很高兴看到运行tail -f
个文件可以正确输出进度条,例如这些条在一行上更新,就像在本地运行tqdm时一样。但是,当我尝试使用python将其包装时,请使用以下函数:
def follow(job : submitit.Job) -> Iterator[str]:
with open(job.paths.stdout) as fo:
with open(job.paths.stderr) as fe:
while True:
lo = fo.readline()
if lo:
yield lo
le = fe.readline()
if le:
yield le
if job.state != 'RUNNING' and not (le or lo):
break
else:
time.sleep(1)
loglines = follow(job)
for line in loglines:
print(line,end='',flush=True)
它不执行此操作,例如我得到一个换行符,并且进度条通过打印新行来更新,它似乎无法处理tqdm正在编写的\x1b[A
字符。
有没有一种方法可以完全在python中做到这一点?
解决方法
我能够通过以下方式解决此问题:使用读取二进制模式,使用read
读取文件的末尾,然后将结果字节解码为ascii
,而不是python 3默认的UTF- 8。更新的工作跟踪功能如下:
def follow(job : Job) -> Iterator[str]:
with open(job.paths.stdout,'rb') as fo:
with open(job.paths.stderr,'rb') as fe:
while True:
lo = fo.read().decode('ascii')
if lo:
yield lo
le = fe.read().decode('ascii')
if le:
yield le
if job.state != 'RUNNING' and not le and not lo:
break
else:
time.sleep(0.1)