从bash文件调用脚本时,iPython embed()会自动退出

时间:2016-12-20 13:30:37

标签: python python-2.7 ipython

我有一个我想调试的数据处理管道设置。 该管道包含一个调用python脚本的bash脚本。

我通常使用iPython的embed()函数进行调试。但是,当从bash文件调用python脚本时,会调用embed()函数但会立即退出,而不会让我干涉。当直接从命令行运行相同的python程序时,我不会观察到这种行为。这是预期的行为,还是我做错了什么?

Python 2.7.6 (default, Oct 26 2016, 20:30:19)
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]:
Do you really want to exit ([y]/n)?
'follow up code prints here'

2 个答案:

答案 0 :(得分:0)

我做了一些实验来查看行为。我注意到,如果任何祖先进程是终端的,IPython会显示控制台。

以下是/ tmp目录中的文件: 的 x.py

import IPython 
IPython.embed()

<强> call.sh

/usr/bin/python /tmp/x.py

<强> call2.sh

/tmp/call.sh

实验1 运行python x.py会打开IPython shell并等待。

实验2 运行bash call.sh也会打开IPython shell并等待。

实验3 运行bash call2.sh也会打开IPython shell并等待。

正如您所看到的,IPython.embed调用的深度并不重要。它始终启动交互式控制台并等待。

让我们试一下,当我们分叉一个新进程时它也可以工作。

<强> fork.sh

/usr/bin/python /tmp/x.py &

实验4 在这种情况下,IPython shell启动但立即退出。请注意&amp;在末尾。它开始了一个不同的过程。在这种情况下,IPython无法访问终端,因此优雅地退出。

答案 1 :(得分:0)

我可以这样复制问题:

# test.py
import IPython
import sys
print(sys.stdin.read())
IPython.embed()
# session
❯ echo 'foo' | python test.py
foo

Python 3.6.8 (default, Oct  7 2019, 12:59:55)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.10.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: Do you really want to exit ([y]/n)?

❯ # I didn't quit on purpose, it happened automatically

STDIN不是TTY,所以我认为IPython担心入站文本(通过管道)将不会被用户键入。它不希望foo(来自上面的示例)涌入IPython shell并执行意外操作。

您可以通过以下方法来解决此问题:通过tty命令获取终端ID,并在完成从管道中的读取后将stdin重定向到调用终端,如下所示:

with open('/dev/pts/16') as user_tty:
    sys.stdin=user_tty
    IPython.embed()

有关tty的更多信息,请参见this post。还要注意,如果在其中放置了错误的tty,来自某些 other 终端的输入将控制IPython。

我不确定IPython是否可能知道调用tty是什么,如果它没有被bash覆盖成为管道的输出端的话。

编辑:这是我的解决方法,简单来说就是:How do I debug a script that uses stdin with ipython?