Ответ 1
Если вы открываете файл без буферизации, он работает:
import subprocess
with open('in.txt', 'rb', 0) as a, open('out.txt', 'w') as b:
header = a.readline()
rc = subprocess.call(['sort'], stdin=a, stdout=b)
Модуль subprocess
работает на уровне дескриптора файла (низкоуровневый небуферизованный ввод-вывод операционной системы). Он может работать с os.pipe()
, socket.socket()
, pty.openpty()
, что угодно с допустимым методом .fileno()
, если OS поддерживает его.
Не рекомендуется смешивать буферизованный и небуферизованный ввод-вывод в том же файле.
В Python 2, file.flush()
появляется сообщение, например:
import subprocess
# 2nd
with open(__file__) as file:
header = file.readline()
file.seek(file.tell()) # synchronize (for io.open and Python 3)
file.flush() # synchronize (for C stdio-based file on Python 2)
rc = subprocess.call(['cat'], stdin=file)
Проблема может быть воспроизведена без модуля subprocess
с os.read()
:
#!/usr/bin/env python
# 2nd
import os
with open(__file__) as file: #XXX fully buffered text file EATS INPUT
file.readline() # ignore header line
os.write(1, os.read(file.fileno(), 1<<20))
Если размер буфера невелик, остальная часть файла печатается:
#!/usr/bin/env python
# 2nd
import os
bufsize = 2 #XXX MAY EAT INPUT
with open(__file__, 'rb', bufsize) as file:
file.readline() # ignore header line
os.write(2, os.read(file.fileno(), 1<<20))
Он потребляет больше ввода, если размер первой строки не равномерно делится на bufsize
.
По умолчанию bufsize
и bufsize=1
(строка-буферизация) ведут себя одинаково на моей машине: начало файла исчезает - около 4 КБ.
file.tell()
сообщает для всех размеров буфера позицию в начале второй строки. Использование next(file)
вместо file.readline()
приводит к file.tell()
около 5K на моей машине на Python 2 из-за ошибки ошибки чтения() io.open()
дает ожидаемую позицию 2-й строки).
Попытка file.seek(file.tell())
до того, как вызов подпроцесса не поможет на Python 2 с файловыми объектами на основе stdio по умолчанию. Он работает с функциями open()
из модулей io
, _pyio
на Python 2 и по умолчанию open
(также io
) на Python 3.
Попытка io
, _pyio
модулей на Python 2 и Python 3 с и без file.flush()
дает различные результаты. Он подтверждает, что смешивание буферизованного и небуферизованного ввода-вывода в одном и том же дескрипторе файла не является хорошей идеей.