我有一个我想调试的数据处理管道设置。 该管道包含一个调用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'
答案 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?