python2.7 使用调试的行为与不使用调试的行为不同

标签 python shell debugging subprocess

我的程序中有一个错误,想使用调试来检查它。在我的 IDE (WingIDE) 中,我有调试功能。但我不能使用从 shell 调用程序。所以我使用Python模块pdb。我的应用程序是单线程的。

我调查过Code is behaving differently in Release vs Debug Mode但这对我来说似乎有些不同。

我将其限制为以下代码。

我做了什么:

我创建了一个简短的方法,只有在不使用 IDE 时才会调用它。

def set_pdb_trace():
    run_in_ide = not sys.stdin.isatty()
    if not run_in_ide:
        import pdb; pdb.set_trace() # use only in python interpreter    

这个工作很好,我在很多情况下都使用过它。

我想调试以下方法:

import sys
import os    
import subprocess32           

def call_backported():
    command = 'lsb_release -r'
    timeout1 = 0.001 # make value too short, so time-out will enforced  
    try:      
        p = subprocess32.Popen(command, shell=True,
                                  stdout=subprocess32.PIPE,
                                  stderr=subprocess32.STDOUT)  
        set_pdb_trace()
        tuple1 = p.communicate(input=b'exit %errorlevel%\r\n', timeout=timeout1)     
        print('No time out')
        value = tuple1[0].decode('utf-8').strip()  
        print('Value : '+ value)
    except subprocess32.TimeoutExpired, e:                  
        print('TimeoutExpired')                            

解释。 我想调用超时的子进程。对于 Python 3.3+,它是内置的,但我的应用程序也能够使用 Python2.7 运行。所以我用了https://pypi.python.org/pypi/subprocess32/3.2.6作为向后移植。 为了读取返回值,我使用了 How to retrieve useful result from subprocess?
没有超时,将超时设置为f.e. 1 秒该方法按预期工作。打印结果值和“无超时”。

我想强制执行超时,因此我将超时设置为非常短的时间 0.001 。所以现在只应该打印“TimeoutExpired”。

我想执行这个shell。 当第一个注释行 #set_pdb_trace() 'TimeoutExpired' 被打印时,这是预期的行为。

现在我取消注释 set_pdb_trace() 并在 shell 中执行。

调试器显示,我按“c”(继续)并打印“无超时”结果。这个结果与没有调试的情况不同。生成输出是:

bernard@bernard-vbox2:~/clones/it-should-work/unit_test$ python test_subprocess32.py 
--Return--
> /home/bernard/clones/it-should-work/unit_test/test_subprocess32.py(22)set_pdb_trace()->None
-> import pdb; pdb.set_trace() # use only in python interpreter
(Pdb) c
No time out
Value : Release:    13.10
bernard@bernard-vbox2:~/clones/it-should-work/unit_test$ 

这怎么可能?又该如何解决?

最佳答案

您在打开子进程和写入子进程之间引入了延迟。

当您创建Popen()对象时,子进程会立即启动。然后,当您调用 p.communicate() 并尝试对其进行写入时,进程尚未完全准备好接收输入,并且延迟以及读取进程输出所需的时间会更长比你的 0.0.1 超时。

当您插入断点时,进程有机会启动; lsb_release 命令不会等待输入并立即生成输出。当调用 p.communicate() 时,无需再等待管道,并且会立即生成输出。

如果您在 Popen() 调用之前放置断点,然后点击 c,您将再次看到超时触发器。

关于python2.7 使用调试的行为与不使用调试的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25379294/

相关文章:

c - 如何调试使用调试信息编译的共享库

python - 将 MS Azure 上麦克风的连续语音识别存储到单独的变量

c# - Windows 7 动画鼠标拖动事件

C#:最佳实践 Debug.Print

c++ - 在 windbg 中查找 STL 双端队列的元素计数

bash - 如何在脚本本身内重定向整个 shell 脚本的输出?

python - Seaborn 箱线图 : get the xtick labels

python - 从 Tkinter gui 更新 matplotlib imshow

Python:将列表列表转换为元组的元组

linux - Linux上的Shell脚本运行java类