python2.7使用调试行为不同,然后没有调试

时间:2014-08-19 08:53:53

标签: python shell debugging subprocess

我的程序中有一个错误,想要使用debug来检查它。在我的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秒方法按预期工作。结果值和'No time out'被打印出来。

我想强制执行超时,因此我将超时设置为非常短的时间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$ 

这怎么可能?以及如何解决?

1 个答案:

答案 0 :(得分:1)

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

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

当您插入断点时,该过程有机会旋转; lsb_release命令不等待输入并立即产生输出。在调用p.communicate()时,不再需要等待管道,并立即生成输出。

如果您在Popen()来电之前设置断点,然后点击c,您将再次看到超时触发。