如何重写sys.stdin以复制输入流

时间:2018-12-19 08:08:32

标签: python python-3.x subprocess

我正在Windows上编写Python 3.6程序,以将所有输入记录到子进程中进行备份。 (由于实际程序是商业产品(exe文件),所以我无法修改子过程代码,而我没有源代码。)

我尝试了以下代码,但它不起作用。文本仅显示在终端中,用于记录的txt文件为空。

Main.py

import subprocess
import sys    

class dup_stream():
    def __init__(self, original_stream, file):
        self.original_stream = original_stream
        self.log = open(file, 'a')

    def write(self, message):
        self.log.write(message)
        self.original_stream.write(message)

    def fileno(self):
        return self.original_stream.fileno()


completed_process = subprocess.run('python Hello.py',
                                   stdin=dup_stream(sys.stdin, 'stdin.txt'),
                                   stderr=dup_stream(sys.stderr, 'stderr.txt'),
                                   stdout=dup_stream(sys.stdout, 'stdout.txt'))

Hello.py

name = input("Your name:") # e.g. "Jane Doe"
print('Hello,',name)

预期结果:

在终端中:

Your name: Jane Doe
Hello, Jane Doe

stdin.txt:

Jane Doe

stdout.txt:

Your name:
Hello, Jane Doe

我之前曾问过一个更普遍的问题(Capture inputs to subprocess.run()),但没有任何实际答案。

2 个答案:

答案 0 :(得分:2)

subprocess很可能会绕过此操作,因为它直接使用fileno

使用stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE。 但是,当时如何转发所有内容并非完全简单。也许最简单的方法是拥有3个线程,每个线程stdinstdoutstderr都从源中读取(例如sys.stdin或{{1 }}),然后将其写入文件和目标(process.stdoutprocess.stdin)。 另请参见here

答案 1 :(得分:0)

我遇到了一个类似的问题,该问题由包装器类解决,而不是通过sys.stdin传递(我只需要记录读取和读取行):

class StdinWrapper(object):

  def __getattribute__(self, name):
    attr = getattr(sys.stdin, name)

    if name == 'readline' or name == 'read':
      def method_with_log(*args, **kwargs):
        result = attr(*args, **kwargs)
        f = open('/tmp/log-input', 'a')
        f.write(result)
        f.close()
        return result
      return method_with_log

    return attr