Почему задание на печать не выполняется до тех пор, пока скрипт python не завершится?
В моем понимании 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 ответ
Я верю, если вы не укажете stdout
в Popen
вызовите его так же, как и родительский процесс, выход которого, вероятно, принадлежит вашей программе.
Попробуйте добавить stdout=subprocess.DEVNULL
(или же stdout=subprocess.PIPE
В случае, если вы хотите захватить этот вывод).
Из документов:
stdin, stdout и stderr определяют стандартный ввод исполняемой программы, стандартный вывод и дескрипторы стандартного файла ошибок соответственно. Допустимые значения: PIPE, DEVNULL, существующий дескриптор файла (положительное целое число), существующий объект файла и None. PIPE указывает, что должна быть создана новая труба для дочернего элемента. DEVNULL указывает, что будет использоваться специальный файл os.devnull. При настройках по умолчанию None перенаправление не происходит; дескрипторы файла ребенка будут унаследованы от родителя.