Две скомпилированные программы на Python неправильно соединяются через каналы - PullRequest
0 голосов
/ 14 января 2019

Я пишу две очень простые программы на Python и пытаюсь соединить их с конвейерами в Linux (CentOS). Первый (называемый бегун) просто печатает, а второй (называемый захватом) должен прочитать эти операторы печати из программы бегуна и распечатать их сам. Но когда я запускаю python runner.pyc | tee capture.pyc, в моей командной строке ничего не происходит. Это просто зависает на каком-то процессе и не заканчивается.

Я немного читал о каналах, но не могу найти что-то подходящее для моей проблемы.

Приведенный ниже код включает в себя некоторые операторы печати только для проверки того, какой файл генерирует оператор печати, и спящий режим в файле runner.py на 3 секунды, поэтому я не генерирую непристойно длинные выходные данные.

runner.py код:

import time

x = 0;
while True:
        print(x)
        x = x + 1
        print("running file")
        time.sleep(3)

код capture.py:

import sys
import time

while True:
    line = sys.stdin.readline()
    print(line)
    print("capture file")

Может ли кто-нибудь объяснить мне, что я делаю неправильно, или указать мне правильное направление?

1 Ответ

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

Проблема вызвана кучей вещей (см. Комментарии к вопросу). Но в программе бегунка нет смыва вывода. Простое добавление flush=True (только Python3) исправляет это, и программа проходит тест cat.

#! /usr/bin/env python3

import time

x = 0;
while True:
    print(x)
    x = x + 1
    print("running file", flush=True)
    time.sleep(1)

Тестирование:

[bash] python3 ./runner.py | cat
0
running file
1
running file
...

Без сброса, вероятно, через некоторое время будет какой-то вывод, но я не буду ждать достаточно долго, чтобы выяснить это. Обычно промывка на print() выполняется в конце строки. Но с помощью канала, по крайней мере в Linux, выделен 4-килобайтный буфер. Есть способ снять с буфера . Но конвейерная буферизация зависит от ОС, поэтому трудно точно понять, что происходит.

Буферизация используется потому, что она тратит впустую ЦП, обрабатывая данные символ за символом, а не обрабатывая целый блок данных сразу.

На стороне захвата sys.stdin.readline() часто возвращает 0-байтовое чтение, поэтому лучше справиться с этим:

#! /usr/bin/env python3

import sys
import time

while True:
    line = sys.stdin.readline()
    if ( len(line) > 0 ):
        print( "Read %u: [%s]" % ( len(line), line.strip() ) )

Тестирование:

[bash] python3 ./runner.py | python3 ./capture.py 

Дает:

python3 ./runner.py | python3 ./capture.py 
Read 2: [0]
Read 13: [running file]
Read 2: [1]
Read 13: [running file]

Вам понадобится метод проверки конца файла на стороне захвата.

...