python - 使用断开连接的标准输入启动 Python 子进程
问题描述
我正在用 Python 执行一个程序,该程序似乎明确地检查是否stdin
正在使用,如果确实如此,它会导致一些不良行为,从而输出一些我不想要的垃圾二进制文件。由于这个原因,我特别不希望程序“看到”任何连接的标准输入。但是,默认情况下,subprocess.run()
连接到父进程的标准输入,因此如果父进程(例如 pytest)有标准输入文件,则测试将失败。
例如说我的测试是这样的(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
断开了标准输入。但是,如果 I 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
标志如何,我的子进程都不会检测到连接的标准输入?
编辑:通过查看我的目标程序(samtools)的源代码,它似乎isatty()
用于检查它是否应该产生输出。所以在这种情况下,看起来我需要愚弄isatty()
。
解决方案
事实证明,这个特定问题涉及欺骗函数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
总是成功,万岁!
推荐阅读
- filter - 使用 RediSearch 过滤 ID
- c++ - C++17文件路径分解成文件夹名
- java - 我们如何将 java 对象传递给 groovyx.net.http.RestClient 的 POST 调用
- java - Replacing elements in array by the larger of its neighbour
- numbers - How do I compare non integer numbers using freemarker templete
- sql - Excel doesn't save SQL query changes
- c++ - 使用声明和实例化中的默认模板参数
- javascript - Reaction CALL_AND_RETRY_LAST
- java - How to extract data from Json array?
- sql - 基于条件的单个查询中的动态 TOP N / TOP 100 PERCENT