使用断开的stdin启动Python子进程

问题描述 投票:0回答:1

我正在Python中执行一个程序,该程序似乎明确检查了是否正在使用stdin,如果这样做,则会导致某些不良行为,从而输出我不需要的垃圾二进制文件。为此,我特别希望not希望程序“查看”任何已连接的stdin。但是,默认情况下,subprocess.run()连接到父级的stdin,因此,如果父级进程(例如pytest)具有stdin文件,则测试将失败。

例如,说我的测试是这个(samtools可以使用conda install -c bioconda samtools安装:]

import subprocess
def test_execute():
    print(subprocess.run(
        ['samtools', 'sort'],
        stdout=subprocess.PIPE,
        encoding='utf-8'
    ))

如果我运行pytest test.py -s,则代码有效,因为-s会断开标准输入。但是,如果我pytest test.py,该命令将输出一些垃圾二进制文件,这将导致测试失败:

>       (result, consumed) = self._buffer_decode(data, self.errors, final)
E       UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

/media/michael/Storage2/miniconda/lib/python3.7/codecs.py:322: UnicodeDecodeError

是否存在某种强制标准输入断开连接的方法,所以无论我的pytest标志如何,我的子进程都将永远不会检测到已连接的标准输入?


编辑:通过查看source code of my target program(samtools),似乎它正在使用isatty()检查它是否应该产生输出。因此,在这种情况下,我需要傻瓜isatty()

python subprocess
1个回答
1
投票

事实证明,此特定问题涉及欺骗函数isatty(),因为这是我的子进程用来确定是否应输出二进制文件的原因。因此,要解决此问题,我只需要将stdin连接到tty:

import subprocess 
import pty # <--------------------------- Added

def test_execute():
    master, slave = pty.openpty() # <---- Added
    print(subprocess.run(
        ['samtools', 'sort'],
        stdout=subprocess.PIPE,
        stdin=slave, # <----------------- Added
        encoding='utf-8'
    ))

现在pytest test.py总是成功,万岁!

© www.soinside.com 2019 - 2024. All rights reserved.