簡體   English   中英

在 Windows10 上編輯 subprocess.Popen(linux 命令)

[英]Edit subprocess.Popen( linux command ) on Windows10

我正在研究與 Superpoint 的圖像匹配( https://github.com/rpautrat/SuperPoint )。

我試圖運行寫在用法區的代碼。 不幸的是,我在 Windows10 和 Superpoint 上使用此代碼為 linux 所以我得到了很多錯誤...... :(

特別是, 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', '-a', '/dev/stderr'], start_new_session=True,
            stdin=subprocess.PIPE, stderr=target_fd, 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)

我會用這個實現 go: https://stackoverflow.com/a/17942748/5430833

首先,'tee' 是一個 linux 實用程序,除非你安裝了一些端口。 /dev/stderr 也是錯誤 output stream 的 unix 描述符。 根據這個答案: cmd.exe 等效於 /dev/stdout,以“作為文件”寫入標准輸出,沒有與 windows 等效的描述符。

如果您希望您的解決方案具有可移植性,我建議您堅持使用 python 並避免使用 Popen,除非您確定您正在啟動的進程在兩個平台上都有效。

編輯:好的,請原諒我,因為我沒有仔細閱讀這個問題。 因此,您需要某種“守護程序”進程來捕獲所有標准輸出和標准錯誤。 如果您可以在控制台中沒有 output 的情況下生活,我會用一個簡單的解決方案 go :注釋掉“capture_outputs”內容並在您的應用程序啟動時(您的測試文件或某種main ,在任何 SuperPoint 代碼執行之前)重定向流:

sys.stdout = open('out.dat', 'w')

在出口的某個地方:

sys.stdout.close()

您可以使用 ContextManager 包裝您的邏輯,以便在某些內部異常文件的情況下正確關閉。

我相信您也可以在“capture_outputs”中進行重定向,但我建議保持簡單,除非我們確定它有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM