我不明白为什么IPython不将某些系统命令的结果分配给python变量。 ack
和ag
可执行文件对我来说似乎一直在发生这种情况
例如,以下命令产生输出:
In [1]: !ack --nocolor foo
bar
1:foo
但是,每当将结果保存到变量中时,我都会得到一个空输出
In [2]: out=!ack --nocolor foo
In [3]: out
Out[3]: []
即使尝试各种技巧,我仍然会遇到此问题:
In [4]: out=!ack --nocolor foo > tmp; sleep 1; cat tmp
In [5]: out
Out[5]: []
实际上,tmp
在最后一种情况下为空,这表明输出捕获将这些命令弄乱了。
有人问这是IPython或ack / ag的问题,还是我对IPython在这里的行为的误解?
答案 0 :(得分:2)
我推断out = !cmd
使用%sx
。这与!cmd
的运行方式不同(请参见%sw
和%system
的文档)。
%sx
经历了几层函数,最终调用了
# import IPython
IPython.utils._process_common.process_handler
其代码类似于@Elliott Frisch在删除的答案中使用的subprocess
调用:
p = subprocess.Popen("ack --nocolor foo", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
我在以下位置提取了process_handler
代码:
def cmd1(astr='ack --nocolor 15 *.txt'):
callback = lambda p: p.communicate()
stderr = subprocess.PIPE
stderr = subprocess.STDOUT
shell = True
close_fds = True
executable = None
p = subprocess.Popen(astr,
shell=shell,
executable=executable,
#stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=stderr,
close_fds=close_fds,
)
out = callback(p)
return out, p.returncode
这有效:
In [40]: cmd1()
Out[40]:
((b'stack53269737.txt:2:11 12 13 14 15 16\ntest.txt:3:11\t12 13 14 15\ntest1.txt:5: 0.054181, 0.506962, 0.315159, 0.653104\n',
None),
0)
但是如果我取消注释stdin
行,它将失败:
In [42]: cmd1()
Out[42]: ((b'', None), 1)
所以是
stdin=subprocess.PIPE,
导致ack
调用失败的参数。不会对其他常见的Shell命令(例如ls
或grep
)造成问题。
ack
帮助包括:
--[no]filter Force ack to treat standard input as a pipe
(--filter) or tty (--nofilter)
将--nofilter
添加到我的命令中(此重定向不需要--nocolor
)
In [50]: cmd1('ack --nofilter 15 *.txt')
Out[50]:
((b'stack53269737.txt:2:11 12 13 14 15 16\ntest.txt:3:11\t12 13 14 15\ntest1.txt:5: 0.054181, 0.506962, 0.315159, 0.653104\n',
None),
0)
In [51]: out = !ack --nofilter 15 *.txt
In [52]: out
Out[52]:
['stack53269737.txt:2:11 12 13 14 15 16',
'test1.txt:5: 0.054181, 0.506962, 0.315159, 0.653104',
'test.txt:3:11\t12 13 14 15']
这就是关键-强制ack
忽略管道输入(尽管我不完全了解细节)。