Почему задание на печать не выполняется до тех пор, пока не завершится сценарий python? - PullRequest
0 голосов
/ 12 сентября 2018

В моем понимании, subprocess.Popen () должен создать новый процесс и не блокировать основной.

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

Похоже, что задание на печать добавляется после нажатия кнопки, но по какой-то причине не выполняется напрямую. (По крайней мере, Ubuntu показывает добавленное задание на печать.)

Почему это происходит?

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess

lpr =  subprocess.Popen("/usr/bin/lpr",              # on raspbian: /usr/bin/lp
                        stdin=subprocess.PIPE,
                        stdout=subprocess.DEVNULL,   # proposed by user elias
                        close_fds=True)              # proposed by user elias

output = "Username: testuser\n".encode() \
         + "Password: p4ssw0rd\n".encode()

lpr.stdin.write(output)

while True:
    pass

Приведенный выше скрипт не печатает ничего, даже после того, как был завершен с помощью ctrl-c (Задание на печать, похоже, остается в очереди.)

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess
import time

lpr =  subprocess.Popen("/usr/bin/lpr",              # on raspbian: /usr/bin/lp
                        stdin=subprocess.PIPE,
                        stdout=subprocess.DEVNULL,   # proposed by user elias 
                        close_fds=True)              # proposed by user elias

output = "Username: testuser\n".encode() \
         + "Password: p4ssw0rd\n".encode()

lpr.stdin.write(output)

time.sleep(20)

Печатается через 20 секунд (после завершения сценария).


О среде исполнения:

  • os : Ubuntu 18.04 (также встречается на распбиане)
  • питон : 3.6.5
  • принтер : сетевой принтер через CUPS (также происходит при подключении через USB)

РЕШЕНИЕ:

Как видно в комментариях к ответу пользователя elias , поведение было вызвано буферизацией.

Проблема была решена закрытием стандартного ввода.

lpr.stdin.close()

1 Ответ

0 голосов
/ 12 сентября 2018

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

Попробуйте добавить stdout=subprocess.DEVNULL (или stdout=subprocess.PIPE, если вы хотите захватить этот вывод).

С документы :

stdin, stdout и stderr задают стандарт исполняемой программыдескриптор ввода, стандартный вывод и стандартный файл ошибок соответственно.Допустимые значения: PIPE, DEVNULL, существующий дескриптор файла (положительное целое число), существующий объект файла и None.PIPE указывает, что должна быть создана новая труба для дочернего элемента.DEVNULL указывает, что будет использоваться специальный файл os.devnull.При настройках по умолчанию None перенаправление не происходит;дескрипторы файла ребенка будут унаследованы от родителя.

...