我试图在文件的一部分被读取后调用该进程。例如:
with open('in.txt', 'r') as a, open('out.txt', 'w') as b:
header = a.readline()
subprocess.call(['sort'], stdin=a, stdout=b)
如果在执行subprocess.call之前我没有从a中读取任何内容,那么这很好,但是如果我从中读取了任何内容,那么子流程就看不到任何内容。这是使用Python2.7.3。我在文档中找不到解释这种行为的任何东西,对子流程源代码的(非常)简短的一瞥并没有揭示原因。
发生这种情况是因为子流程模块从文件对象中提取文件句柄。
http://hg.python.org/releasing/2.7.6/file/ba31940588b6/Lib/subprocess.py
第1126行,来自701。
文件对象使用缓冲区,并且在子进程提取它时已经从文件句柄中读取了很多内容。
我在Python2.7中通过对齐文件描述符位置解决了这个问题。
os.lseek(_file.fileno(), _file.tell(), os.SEEK_SET) truncate_null_cmd = ['tr','-d', '\\000'] subprocess.Popen(truncate_null_cmd, stdin=_file, stdout=subprocess.PIPE)
如果未缓冲地打开文件,则可以:
subprocess
模块在文件描述符级别(操作系统的低级别无缓冲I/O)工作。它可以与os.pipe()
、socket.socket()
、pty.openpty()
一起工作,如果操作系统支持的话,它可以使用任何有效的.fileno()
方法。不建议在同一文件上混合缓冲和非缓冲I/O。
在Python 2上,
file.flush()
会导致输出出现,例如:没有
subprocess
模块和os.read()
可以复制此问题:如果缓冲区大小很小,则打印文件的其余部分:
如果第一行的大小不能被
bufsize
整除,它将消耗更多的输入。默认的
bufsize
和bufsize=1
(行缓冲)在我的机器上的行为类似:文件的开头消失了——大约4KB。file.tell()
为所有缓冲区大小报告第2行开头的位置。使用next(file)
而不是file.readline()
会导致file.tell()
在Python 2上,由于read-ahead buffer bug(io.open()
给出了预期的第二行位置),所以在我的机器上大约有5公里。在调用子进程之前尝试
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不是一个好主意。相关问题 更多 >
编程相关推荐