ale*_*kot 8 python console file stringio
我正在使用subprocess
包从 python 脚本调用一些外部控制台命令,我需要将文件处理程序传递给它以分别返回stdout和stderr。代码大致如下:
import subprocess
stdout_file = file(os.path.join(local_path, 'stdout.txt'), 'w+')
stderr_file = file(os.path.join(local_path, 'stderr.txt'), 'w+')
subprocess.call(["somecommand", "someparam"], stdout=stdout_file, stderr=stderr_file)
Run Code Online (Sandbox Code Playgroud)
这工作正常,并且正在创建具有相关输出的 txt 文件。然而,在忽略文件创建的内存中处理这些输出会更好。所以我使用 StringIO 包来处理它:
import subprocess
import StringIO
stdout_file = StringIO.StringIO()
stderr_file = StringIO.StringIO()
subprocess.call(["somecommand", "someparam"], stdout=stdout_file, stderr=stderr_file)
Run Code Online (Sandbox Code Playgroud)
但这不起作用。失败:
File "./test.py", line 17, in <module>
subprocess.call(["somecommand", "someparam"], stdout=stdout_file, stderr=stderr_file)
File "/usr/lib/python2.7/subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 672, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/usr/lib/python2.7/subprocess.py", line 1063, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
Run Code Online (Sandbox Code Playgroud)
我看到它缺少本机文件对象的某些部分并因此失败。
所以这个问题比实际更具教育意义 - 为什么 StringIO 中缺少文件接口的这些部分,是否有任何原因无法实现?
Van*_*pps 10
正如您在评论中所说,Popen
和Popen.communicate
是这里正确的解决方案。
一点背景知识:真实的文件对象具有文件描述符,这是对象所缺少的fileno
属性。StringIO
它们只是普通的整数:您可能熟悉文件描述符 0、1 和 2,它们分别是stdin
、stdout
和stderr
。如果一个进程打开了更多文件,它们会被分配 3、4、5 等。您可以使用 来查看进程的当前文件描述符lsof -p
。
那么,为什么对象不能StringIO
有文件描述符呢?为了获得一个,它需要打开一个文件或打开一个管道*。打开文件没有意义,因为不打开文件才是使用的全部目的StringIO
。
打开管道也没有意义,即使它们像StringIO
对象一样存在于内存中。它们用于通信,而不是存储:seek
、truncate
、len
对于管道来说根本没有任何意义,并且其行为read
与write
对于文件的行为非常不同。当您read
从管道中删除返回的数据时,将从管道的缓冲区中删除,如果当您尝试删除该(相对较小的)缓冲区已满时write
,您的进程将挂起,直到read
从管道中删除某些内容以释放缓冲区空间。
因此,如果您想将字符串用作stdin
或stdout
用于stderr
子进程,则StringIO
不会削减它,但它Popen.communicate
是完美的。如上所述(并在subprocess
文档中警告过),正确读取和写入管道很复杂。Popen
为您处理这种复杂性。
* 我想我理论上可以想象第三种文件描述符对应于进程之间共享的内存区域?不太确定为什么不存在。但是,呃,我不是内核开发人员,所以我确信这是有原因的。