首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python子进程“对象没有属性'fileno'”错误

Python子进程“对象没有属性'fileno'”错误
EN

Stack Overflow用户
提问于 2009-04-22 16:05:06
回答 5查看 19.2K关注 0票数 7

当使用Python2.5.1运行时,这段代码生成"AttributeError:'Popen‘object has no attribute 'fileno'“

代码:

代码语言:javascript
复制
def get_blame(filename): 
    proc = []
    proc.append(Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE))
    proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)
    proc.append(Popen(['tr', r"'\040'", r"';'"], stdin=proc[-1]), stdout=PIPE)
    proc.append(Popen(['cut', r"-d", r"\;", '-f', '3'], stdin=proc[-1]), stdout=PIPE)
    return proc[-1].stdout.read()

堆栈:

代码语言:javascript
复制
function walk_folder in blame.py at line 55
print_file(os.path.join(os.getcwd(), filename), path)

function print_file in blame.py at line 34
users = get_blame(filename)

function get_blame in blame.py at line 20
proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

function __init__ in subprocess.py at line 533
(p2cread, p2cwrite,

function _get_handles in subprocess.py at line 830
p2cread = stdin.fileno()

这段代码应该适用于python文档中描述的this usage

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-04-22 16:15:09

三件事

首先,你的()是错误的。

其次,subprocess.Popen()的结果是一个进程对象,而不是一个文件。

代码语言:javascript
复制
proc = []
proc.append(Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE))
proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

proc[-1]的值不是文件,而是包含文件的进程。

代码语言:javascript
复制
proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1].stdout, stdout=PIPE))

第三,不要在shell中做所有的trcut垃圾,几乎没有比这更慢的了。用Python语言编写trcut处理--它更快、更简单。

票数 10
EN

Stack Overflow用户

发布于 2009-04-22 17:13:09

剧本里有一些奇怪的东西,

  • 为什么要将每个进程存储在列表中?简单地使用变量不是更具可读性吗?删除所有.append()s会显示一个语法错误,您多次将stdout=PIPE传递给append参数,而不是passed:

Proc.append(打开(...),stdout=PIPE)

因此,直接重写(仍然有错误,我稍后会提到)将变成..

定义剪切(文件名):get_blame= Popen('svn',‘def’,shellquote(文件名),stdout=PIPE) tr1 = Popen('tr','-s',r"'\040'",stdin=blame,stdout=PIPE) tr2 = Popen('tr',r"'\040'",r"';'",stdin=tr1),stdout=PIPE) cut = Popen('cut',r"-d",r"\;",'-f','3',stdin=tr2,stdout=PIPE)返回打开每个后续命令,您传递的是cut.stdout.read()

  • On对象,而不是处理stdout的对象。从子流程文档的"Replacing shell pipeline"部分,您需要..

p1 = Popen("dmesg",stdout=PIPE) p2 = Popen("grep","hda",stdin=p1.stdout,stdout=PIPE)

你所做的等同于stdin=p1

tr1 = (在上面重写的代码中)行将变为..

stdout=PIPE)

  • You = tr1 (‘tr’,'-s',r"'\040'",stdin=blame.stdout,shell不需要用子进程对命令/参数进行转义,因为子进程不会在任何外壳中运行命令(除非指定shell=True)。请参见子流程文档的Security部分。

而不是..

Proc.append(打开(‘svn’,‘proc.append’,外壳引号(文件名),stdout=PIPE))

..you可以安全地这样做..

Popen('svn',‘stdout=PIPE)

  • As’,filename,S.Lott建议,不要使用子进程来做在Python语言中更容易完成的文本操作( tr/cut命令)。首先,tr/cut等的可移植性不是很好(不同版本有不同的参数),而且它们也很难读懂(我不知道tr和cut在做什么)

如果我要重写这个命令,我可能会这样做。

def get_blame(文件名):Popen=打开(‘svn’,‘Popen’,文件名,stdout=PIPE) output = blame.communicate() #首选于blame.stdout.read() #处理命令输出: ret = []表示output.split中的行(“\n "):split_line = line.strip().split(”“) if len( split_line ) > 2: rev =split_line author = split_line1 line =”".join(split_line2:) ret.append({'rev':rev,'author':author,'line':line}) return ret

票数 3
EN

Stack Overflow用户

发布于 2009-04-22 16:11:55

如果您希望获得进程的标准输出,那么请用stdin=proc[-1].stdout替换您的stdin=proc[-1]

另外,你需要移动你的paren,它应该在stdout参数之后。

代码语言:javascript
复制
 proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

应该是:

代码语言:javascript
复制
 proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1].stdout, stdout=PIPE))

用同样的方法修复你的其他append调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/777996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档