Как сделать обработку ошибок с трубами подпроцесса - PullRequest
0 голосов
/ 16 января 2019

Кажется, я не могу получить доступ к process.stdout дважды. Но я не уверен, как обойти это. Я пытаюсь перехватить любые ошибки git, вызванные моей командой, и перехватить любой полезный вывод.

Если выходные данные ошибочны или отсутствуют, я хотел бы знать об этом, чтобы не пытаться изменить переменную, которая не существует или не имеет смысла.

Однако, похоже, что, проверяя вывод на наличие ошибок, я теряю способность фиксировать значимый вывод.

Есть ли лучший способ сделать это, чтобы я мог удовлетворить оба сценария?

Пока что я только что попробовал две перестановки. Но когда я сначала проверяю правильность, я не могу получить доступ к выводу, чтобы что-то с ним сделать. Однако, если я пытаюсь использовать его без проверки, я теряю обработку ошибок.

def gitinfo(sha1, placeholder, repoDir = '/mnt/d/stash.projects/rea'):
    placeholders = {'hash':'%H', 'comment':'%s', 'time':'%cd', 'newline':'%n'}

    if placeholder not in placeholders:
        print('Error: function gitinfo is not programmed for paceholder: ' + placeholder)
        print('Please see source, or try \'hash\', \'comment\', \'time\', or \'newline\'.')
        return 'Good day.'

    format_option = '--format="' + str(placeholders[placeholder.lower()]) + '"'
    date_format = '%Y-%m-%d %H:%M:%S'
    date_option = '--date=format:\'' + date_format + '\''
    cmd = ['git', 'show', format_option, date_option, '-s', sha1]

    with subprocess.Popen(cmd, cwd=repoDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) as proc:

        if not proc.stdout.read():
            warn(proc.stderr.read())
            return 'Error retrieving ' + placeholder + ' in function gitinfo.'


        for line in proc.stdout:
            result = line.rstrip('\n')


    if placeholder.lower() == 'time':
        result = result.replace("'", "")

    return result

1 Ответ

0 голосов
/ 16 января 2019

stdout и stderr - это не строки, а потоки. Один из способов думать о них, как о резервуаре для воды: процесс сбрасывает воду в верхнюю часть, и у вас есть кран внизу, к которому вы можете получить доступ. stdout.read() говорит: «откройте кран и дайте ему поработать, пока в резервуаре больше не будет воды» - если вы не поместили ведро под кран (назначая переменную в этой аналогии), вода исчезнет, ​​и открытие крана из пустого резервуара снова не вернет его.

Если вам нужно обращаться к одному и тому же выводу из потока несколько раз, вам нужно сохранить его в переменной, а затем ссылаться на эту переменную каждый раз. В вашем случае вы можете сделать что-то вроде:

output = proc.stdout.read()
if not output:
    # your error handling here
for line in output.split("\n"):
    # do stuff with line here
...