Запуск подпроцесса Python с отключенным стандартным вводом - PullRequest
0 голосов
/ 29 мая 2020

Я выполняю программу на Python, которая, кажется, явно проверяет, используется ли stdin, и если это так, это приводит к некоторому нежелательному поведению, в результате чего выводится какой-то мусорный двоичный файл, который мне не нужен. Я специально не хочу, чтобы программа "видела" любой подключенный стандартный ввод по этой причине. Однако по умолчанию subprocess.run() подключается к родительскому стандартному вводу, и поэтому, если родительский процесс (например, 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

Есть ли способ заставить stdin отключиться, так что независимо от моих pytest флагов, мой подпроцесс никогда не обнаружит подключенный стандартный ввод?


Изменить: глядя на исходный код моей целевой программы (samtools), кажется, что он использует isatty() для проверки если он должен производить вывод. Так что в данном случае мне нужно обмануть isatty().

1 Ответ

1 голос
/ 29 мая 2020

Оказывается, эта специфическая проблема c связана с обманом функции 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 всегда успешно, ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...