IPython不会捕获某些命令输出(例如,ack) [英] IPython won't capture some command outputs (e.g., ack)
问题描述
我不明白为什么IPython不将某些系统命令的结果分配给python变量.我似乎经常在 ack
和
I don't understand why IPython does not assign the result of some system command to python variables. This seems to constantly happen to me to the ack
and ag
executables
例如,以下命令产生输出:
For example, the following command produces output:
In [1]: !ack --nocolor foo
bar
1:foo
但是,每当将结果保存到变量中时,我都会得到一个空输出
However, whenever I save that result to a variable, I get an empty output
In [2]: out=!ack --nocolor foo
In [3]: out
Out[3]: []
即使尝试各种技巧,我也会遇到此问题:
I get this problem even when I try all sorts of hacks:
In [4]: out=!ack --nocolor foo > tmp; sleep 1; cat tmp
In [5]: out
Out[5]: []
实际上,在最后一种情况下,tmp
为空,这表明输出捕获将这些命令弄乱了.
In fact, tmp
is empty in the last case, which suggests that the output capture messes up with these commands.
有人问这是IPython或ack/ag的问题,还是我对IPython在这里的行为的误解?
Does anyone how if this is a problem with IPython or ack/ag, or simply my misunderstanding of how IPython should behave here?
推荐答案
我推断out = !cmd
使用%sx
.这与!cmd
的运行方式不同(请参见%sw
和%system
的文档).
I've deduced that out = !cmd
uses %sx
. This is different from how !cmd
is run (see docs for %sw
and %system
).
%sx
经过几层函数,最终调用
%sx
goes through several layers of functions, and ends up calling
# import IPython
IPython.utils._process_common.process_handler
其代码类似于@Elliott Frisch在删除的答案中使用的subprocess
调用:
Its code is similar to the subprocess
call that @Elliott Frisch uses in his deleted answer:
p = subprocess.Popen("ack --nocolor foo", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
我在以下位置提取了process_handler
代码:
I abstracted the process_handler
code in:
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
行,它将失败:
But if I uncomment the stdin
line, it fails:
In [42]: cmd1()
Out[42]: ((b'', None), 1)
所以是
stdin=subprocess.PIPE,
导致ack
调用失败的
参数.不会导致其他常见的Shell命令(例如ls
或grep
)出现问题.
parameter that causes the ack
call to fail. It doesn't cause problems with other common shell commands like ls
or grep
.
ack
帮助具有:
--[no]filter Force ack to treat standard input as a pipe
(--filter) or tty (--nofilter)
将--nofilter
添加到我的命令中(此重定向不需要--nocolor
):
Adding --nofilter
to my commands (--nocolor
isn't needed with this redirection):
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
忽略管道输入(尽管我不完全了解细节).
So that's the key - force ack
to ignore the piped input (though I don't fully understand the details).
这篇关于IPython不会捕获某些命令输出(例如,ack)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!