问题描述
我正在研究Superpoint(https://github.com/rpautrat/SuperPoint)的图像匹配。
我试图运行在用法区域中编写的代码。不幸的是,我在Windows10和为Linux编写的Superpoint上使用此代码,所以我遇到很多错误...:(
特别是https://github.com/rpautrat/SuperPoint/blob/master/superpoint/utils/stdout_capturing.py对我造成严重错误。
subprocess.Popen的一部分,用于使用文件描述符写入日志文件。 我想获得与从Linux操作系统获得的结果相同的日志文件结果。
代码在下面。...,我认为 tee 命令在Windows上不起作用,这就是该部分导致错误的原因。
我希望为运行Superpoint的整个代码进行编辑。
请让我知道Windows10问题上此文件描述符的解决方案。
非常感谢您的帮助!
#!/usr/bin/env python
# coding=utf-8
from __future__ import division,print_function,unicode_literals
import os
import sys
import subprocess
from threading import Timer
from contextlib import contextmanager
'''
Based on sacred/stdout_capturing.py in project Sacred
https://github.com/IDSIA/sacred
'''
def flush():
"""Try to flush all stdio buffers,both from python and from C."""
try:
sys.stdout.flush()
sys.stderr.flush()
except (AttributeError,ValueError,IOError):
pass # unsupported
# Duplicate stdout and stderr to a file. Inspired by:
# http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/
# http://stackoverflow.com/a/651718/1388435
# http://stackoverflow.com/a/22434262/1388435
@contextmanager
def capture_outputs(filename):
"""Duplicate stdout and stderr to a file on the file descriptor level."""
# with NamedTemporaryFile(mode='w+') as target:
with open(filename,'a+') as target:
original_stdout_fd = 1
original_stderr_fd = 2
target_fd = target.fileno()
# Save a copy of the original stdout and stderr file descriptors
saved_stdout_fd = os.dup(original_stdout_fd)
saved_stderr_fd = os.dup(original_stderr_fd)
tee_stdout = subprocess.Popen(
['tee','-a','/dev/stderr'],start_new_session=True,stdin=subprocess.PIPE,stderr=target_fd,stdout=1)
tee_stderr = subprocess.Popen(
['tee',stdout=2)
flush()
os.dup2(tee_stdout.stdin.fileno(),original_stdout_fd)
os.dup2(tee_stderr.stdin.fileno(),original_stderr_fd)
try:
yield
finally:
flush()
# then redirect stdout back to the saved fd
tee_stdout.stdin.close()
tee_stderr.stdin.close()
# restore original fds
os.dup2(saved_stdout_fd,original_stdout_fd)
os.dup2(saved_stderr_fd,original_stderr_fd)
# wait for completion of the tee processes with timeout
# implemented using a timer because timeout support is py3 only
def kill_tees():
tee_stdout.kill()
tee_stderr.kill()
tee_timer = Timer(1,kill_tees)
try:
tee_timer.start()
tee_stdout.wait()
tee_stderr.wait()
finally:
tee_timer.cancel()
os.close(saved_stdout_fd)
os.close(saved_stderr_fd)
解决方法
我将使用以下实现:https://stackoverflow.com/a/17942748/5430833
首先,'tee'是一个Linux实用程序,除非您已经安装了一些端口。 / dev / stderr还是错误输出流的Unix描述符。按照这个答案:cmd.exe equivalent of /dev/stdout,to write to stdout 'as a file',Windows没有这样的描述符。
如果您希望您的解决方案具有可移植性,那么我建议您坚持使用python并避免使用Popen,除非您确定要启动的进程在两个平台上都可以使用。
编辑:好的,请原谅我,因为我没有仔细阅读问题。因此,您需要某种“守护进程”来捕获所有stdout和stderr。如果您可以在控制台中保持无输出状态,那么我将提供一个简单的解决方案:在您的应用程序启动时(您的测试文件或某种 main )注释掉'capture_outputs'内容任何执行的SuperPoint代码)重定向流:
sys.stdout = open('out.dat','w')
在出口处的某个地方:
sys.stdout.close()
您可以使用ContextManager包装您的逻辑,以便在某些内部异常文件被正确关闭的情况下。
我相信您也可以在“ capture_outputs”中进行重定向,但是我建议保持简化,除非我们确定它可以正常工作。