如果您以无缓冲的方式打开文件,则可以运行:
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
模块基于文件描述符级别工作(操作系统的低级别无缓冲I/O)。它可以与os.pipe()
、socket.socket()
、pty.openpty()
等任何具有有效的.fileno()
方法的对象一起使用,如果操作系统支持。
不建议在同一文件上混合使用缓冲和无缓冲I/O。
在Python 2中,file.flush()
会导致输出出现,例如:
import subprocess
with open(__file__) as file:
header = file.readline()
file.seek(file.tell())
file.flush()
rc = subprocess.call(['cat'], stdin=file)
使用 os.read()
无需 subprocess
模块即可重现此问题:
#!/usr/bin/env python
import os
with open(__file__) as file:
file.readline()
os.write(1, os.read(file.fileno(), 1<<20))
如果缓冲区大小较小,则会打印文件的其余部分。
import os
bufsize = 2
with open(__file__, 'rb', bufsize) as file:
file.readline()
os.write(2, os.read(file.fileno(), 1<<20))
如果第一行大小不能被bufsize
整除,则会更多地消耗输入。
在我的机器上,默认的bufsize
和bufsize=1
(行缓冲)的行为类似:文件开头消失了-大约4KB。
对于所有缓冲区大小,file.tell()
报告的位置都在第二行开头。在Python 2中,使用next(file)
而不是file.readline()
会导致file.tell()
大约为5K,这是由于读取前缓冲区错误(io.open()
给出了预期的第二行位置)。
在子进程调用之前尝试file.seek(file.tell())
对于默认基于stdio的文件对象的Python 2无效。它可以在Python 2的io
、_pyio
模块中使用open()
函数,并且可以在Python 3的默认open
(也是基于io
的)中使用。
在Python 2和Python 3中尝试使用io
、_pyio
模块,有无file.flush()
会产生不同的结果。这证实了在同一文件描述符上混合缓冲和非缓冲I/O不是一个好主意。