IPython不会捕获某些命令输出(例如,ack) [英] IPython won't capture some command outputs (e.g., ack)

查看:53
本文介绍了IPython不会捕获某些命令输出(例如,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命令(例如lsgrep)出现问题.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆