2013-06-12 25 views
15

我試圖調試一個Python CLI,我寫了可以從stdin取其參數。一個簡單的測試用例將有如何調試採用stdin的python CLI?

輸出
echo "test" | python mytool.py 

是相當於

python mytool.py test 

輸出我想調試的一些問題有了這個工具,所以我試圖運行這個命令:

echo "test" | pdb mytool.py 

,但我得到這個輸出,然後退出PDB:

> /path/to/mytool.py(5)<module>() 
-> ''' 
(Pdb) *** NameError: name 'test' is not defined 
(Pdb) 

當我將-m python添加到shebang,並且如果我在腳本內部運行pdb.set_trace()時,會發生同樣的情況。

這是怎麼回事嗎?

+2

你可以改變你的腳本接受來自stdin以外的文件的輸入嗎? – nmichaels

+0

[Python CLI程序單元測試]的可能重複(http://stackoverflow.com/questions/13493288/python-cli-program-unit-testing) –

+1

@ user1901786如何訪問CLI腳本中的stdin?使用'sys.stdin'?另外,你只是想爲此寫一個測試,還是需要在腳本中啓動調試器?如果您需要調試器,那麼您希望它參與腳本?對不起,這個問題對我來說有點不清楚。 – famousgarkin

回答

0

當您使用pdb(或任何其他python調試器)時,它獲取調試命令的stdin,這就是爲什麼您會得到NameError: name 'test' is not defined

例如這個命令會在運行時的乞討退出調試器,你不會得到這個錯誤(也沒有交互式調試)的一個運行:

(回聲續;回聲「測試」)| python -m pdb mytool.py

+2

雖然這解釋了發生了什麼,但它不提供答案。 – whereswalden

3

您可以使用其他文件描述符。隨着bash,那麼你可以創建一個新的文件描述符:

exec 3<> test.txt 

,然後在你的Python文件中有這樣的:

#!/usr/bin/python 

# Use fd 3 as another stdin file. 
import os 
stdin=os.fdopen(3) 

while True: 
    s=stdin.readline() 
    import pdb; pdb.set_trace() 
    print len(s) 

只是乳寧你的腳本將使用的test.txt作爲輸入,和你可以在stdin上使用stdin。如果需要,它也可以用於管道。

+3

我更喜歡不需要修改工具代碼的解決方案。 – whereswalden

9

另一種選擇是創建你自己的Pdb對象,並在那裏設置標準輸入和標準輸出。我的概念驗證涉及2個終端,但肯定有些工作可以合併某種非常不安全的網絡服務器。

  1. 創建兩個FIFO: mkfifo stdin mkfifo stdout

  2. 在一個終端,在後臺打開stdout和寫入標準輸入: cat stdout & cat > stdin

  3. 在Python代碼/控制檯創建PDB對象,使用它: import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) ... mypdb.set_trace() ...
  4. 利潤!

您應該可以在第一個控制檯上使用pdb。

唯一的缺點是必須使用自定義PDB,但有些猴子在INIT修補(PYTHONSTARTUP或類似)可以幫助:

import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) pdb.set_trace=mydbp.set_trace

0

你控制TTY仍然是一個終端,對不對?使用此代替pdb.set_trace

def tty_pdb(): 
    from contextlib import (_RedirectStream, 
          redirect_stdout, redirect_stderr) 
    class redirect_stdin(_RedirectStream): 
     _stream = 'stdin' 
    with open('/dev/tty', 'r') as new_stdin, \ 
     open('/dev/tty', 'w') as new_stdout, \ 
     open('/dev/tty', 'w') as new_stderr, \ 
     redirect_stdin(new_stdin), \ 
     redirect_stdout(new_stdout), redirect_stderr(new_stderr): 
     __import__('pdb').set_trace() 

在這些情況下沒有獲得readline自動完成。向上箭頭也不起作用,或任何其他的readline細線。