python StringIO不能用作subrpocess.call()的文件
我正在使用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) 这工作正常,并且正在创建具有相关输出的txt文件.然而,在内存中处理这些输出而忽略文件创建会更好.所以我使用StringIO包来这样处理它: import subprocess import StringIO stdout_file = StringIO.StringIO() stderr_file = StringIO.StringIO() subprocess.call(["somecommand",stderr=stderr_file) 但这不起作用.失败: File "./test.py",line 17,in <module> subprocess.call(["somecommand",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' 我看到它丢失了本机文件对象的某些部分并因此而失败. 所以这个问题更具教育性而非实际性 – 为什么StringIO中缺少文件接口的这些部分,是否有任何原因导致无法实现? 解决方法
正如您在评论中所说,Popen和Popen.communicate是正确的解决方案.
一些背景知识:真实文件对象有文件描述符,这是缺少StringIO对象的fileno属性.它们只是普通的整数:你可能熟悉文件描述符0,1和2,它们分别是stdin,stdout和stderr.如果进程打开了更多文件,则会为它们分配3,4,5等.您可以使用lsof -p查看进程的当前文件描述符. 那么,为什么StringIO对象不能有文件描述符?为了获得一个,它需要打开文件或打开管道*.打开文件是没有意义的,因为不首先打开文件就是使用StringIO的重点. 打开一个管道也没有意义,即使它们像StringIO对象一样存在于内存中.它们用于通信,而不是存储:seek,truncate和len对管道没有任何意义,并且读取和写入的行为与文件的行为完全不同.当您从管道读取时,返回的数据将从管道的缓冲区中删除,如果在您尝试写入时该(相对较小的)缓冲区已满,则您的进程将挂起,直到从管道读取某些内容以释放缓冲区空间. 因此,如果您想将字符串用作stdin,stdout或stderr作为子进程,StringIO将不会删除它,但Popen.communicate是完美的.如上所述(并在子流程的文档中警告),正确读取和写入管道是复杂的. Popen为您处理这种复杂性. *我想我理论上可以想象第三种文件描述符对应于进程之间共享的内存区域?不确定为什么不存在.但是,我不是内核开发人员,所以我确信这是有原因的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |