我正在編寫一個小的Python IDE,我想添加簡單的調試。我不需要winpdb的所有功能。 如何啓動一個python程序(通過文件名)並將一個斷點設置爲行號,以使其運行到該行號並暫停? 請注意,我不想從命令行執行此操作,並且我不想編輯源代碼(例如,通過插入set_trace)。我不希望它停在第一行,所以我必須從那裏運行調試器。我已經用pdb和bdb嘗試了所有顯而易見的方法,但我必須缺少一些東西。從程序運行python調試會話,而不是從控制檯運行
回答
幾乎是唯一可行的方法(據我所知)是從您的IDE中運行Python作爲子進程。這樣可以避免當前Python解釋器造成的「污染」,這使得程序運行的可能性與您獨立開始運行的可能性相當。 (如果你有這樣的問題,檢查進程環境中)。在這種方式下,你可以使用
p = subprocess.Popen(args=[sys.executable, '-m', 'pdb', 'scriptname.py', 'arg1'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
這將在調試器提示符啓動Python的運行在「調試模式」的腳本。你需要運行一些調試器命令來設置斷點,你可以做像這樣:
o,e = p.communicate('break scriptname.py:lineno')
如果一切正常,o
應該是Python解釋器的正常輸出它設置一個斷點後,和e
應空着。我建議你玩這個,並在你的代碼中添加一些檢查,以確保斷點是否正確設置。
之後,你就可以啓動程序與
p.communicate('continue')
運行在這一點上,你可能會想鉤輸入,輸出和錯誤流達,你在嵌入控制檯您IDE。你可能會需要一個事件循環,要做到這一點,大概像這樣:
while p.returncode is None:
o,e = p.communicate(console.read())
console.write(o)
console.write(e)
您應該考慮到段得到有效的僞代碼,因爲這取決於究竟如何控制檯的作品,它可能會採取一些修修補補來修正它。
如果這看起來過於凌亂,你也許可以簡化這個過程有點使用Python的pdb
和bdb
模塊功能(我猜分別爲「Python調試」,並基本調試器」)。關於如何做的最好的參考資料這是pdb
模塊本身的源代碼。基本上,模塊的責任分開的方式是bdb
處理「引擎蓋下」調試器功能,如設置斷點或停止並重新啓動執行; pdb
是對此的封裝它處理用戶交互,即讀取命令和顯示輸出。
對於你的IDE集成的調試器,它將有助於調節t時的pdb
模塊的,我能想到的兩種行爲:
- 初始化過程中,系統將自動設置斷點,您無需顯式地發送文本命令這樣做
- 使其採取從輸入並將輸出發送到您的IDE控制檯
只需通過繼承pdb.Pdb
即可輕鬆實現這兩項更改。您可以創建一個子類,其初始化需要斷點的列表,作爲一個額外的參數:
class MyPDB(pdb.Pdb):
def __init__(self, breakpoints, completekey='tab',
stdin=None, stdout=None, skip=None):
pdb.Pdb.__init__(self, completekey, stdin, stdout, skip)
self._breakpoints = breakpoints
實際設置斷點邏輯的地方是調試器讀取其.pdbrc
文件,它發生在pdb.Pdb.setup
方法之後。來執行實際的設置中,使用set_break
方法從bdb.Bdb
繼承:
def setInitialBreakpoints(self):
_breakpoints = self._breakpoints
self._breakpoints = None # to avoid setting breaks twice
for bp in _breakpoints:
self.set_break(filename=bp.filename, line=bp.line,
temporary=bp.temporary, conditional=bp.conditional,
funcname=bp.funcname)
def setup(self, f, t):
pdb.Pdb.setup(self, f, t)
self.setInitialBreakpoints()
這段代碼將工作每個斷點作爲例如被傳遞一個命名的元組。您也可以嘗試直接構建bdb.Breakpoint
實例,但我不確定這是否可以正常工作,因爲bdb.Bdb
保留有關斷點的自己的信息。
接下來,您需要爲您的模塊創建一個新的main
方法,該方法以與運行pdb
相同的方式運行。在某種程度上,您可以從pdb
(和當然的if __name__ == '__main__'
聲明)複製main
方法,但您需要用某種方式來擴充它,以傳入有關其他斷點的信息。什麼我建議是寫斷點從你的IDE中的臨時文件,並作爲第二個參數傳遞一個文件的名稱:在mypdb.main()
tmpfilename = ...
# write breakpoint info
p = subprocess.Popen(args=[sys.executable, '-m', 'mypdb', tmpfilename, ...], ...)
# delete the temporary file
然後,你會增加這樣的事情:
def main():
# code excerpted from pdb.main()
...
del sys.argv[0]
# add this
bpfilename = sys.argv[0]
with open(bpfilename) as f:
# read breakpoint info
breakpoints = ...
del sys.argv[0]
# back to excerpt from pdb.main()
sys.path[0] = os.path.dirname(mainpyfile)
pdb = Pdb(breakpoints) # modified
現在,您可以像使用pdb
一樣使用新的調試器模塊,不同之處在於您無需在過程啓動之前明確發送break
命令。這具有如下優點:如果允許您這樣做,則可以直接將Python子進程的標準輸入和輸出掛接到控制檯。
感謝您的意見。但是,一旦到達p.communicate('continue'),我就會收到ValueError:關閉文件的I/O操作。 在Popen中使用close_fds = False並沒有幫助... –
@antwin:請記住,所有這些本質上都是僞代碼。如果你只是運行它,當然你會得到各種各樣的錯誤。您需要根據自己的項目來調整它,但是我無法告訴您任何有關您的源代碼的信息。 –
確實!因此,我將您的建議解壓到以下文件中:#!/ usr/bin/python import sys,subprocess fileName ='/tmp/test.py' lineno = 4 p = subprocess.Popen(args = [sys.executable ,'-m','pdb',fileName], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) cmd ='break%s:%d'%(fileName,lineno ); print cmd o,e = p.communicate(cmd) p.communicate('continue') 它應該工作,並且我以前使用過類似的方法,但它仍然給出ValueError:關閉文件的I/O操作第一次溝通之後... –
- 1. jquery代碼不會從頁腳加載運行,而是從控制檯運行
- 2. 從Eclipse控制檯運行java程序
- 3. 從控制檯運行java
- 4. 從控制檯運行gimp
- 5. 運行從SBT控制檯
- 6. 從控制檯運行xunit
- 7. 獨立於測試從控制檯運行程序
- 8. 試圖從控制檯應用程序運行WebTest
- 9. Phantom.js不能從OSX控制檯運行
- 10. 從其他控制檯應用程序運行控制檯應用程序
- 11. IO程序不能從控制檯運行,但它通過Eclipse(Java)運行
- 12. 如何檢查程序是否從控制檯運行?
- 13. 系統命令從控制檯運行,但不是從linux中的crontab運行
- 14. 從Windows XAML應用程序運行控制檯應用程序
- 15. 如何從控制檯應用程序運行程序?
- 16. 從SciTE運行時控制檯程序無法正確執行
- 17. 從不同的項目運行控制檯應用程序
- 18. 從幾臺Windows機器上的控制檯運行MPI程序
- 19. 調試!程序不會運行
- 20. 如何判斷是否在Linux控制檯中運行而不是在ssh會話中運行?
- 21. 從控制器的Symfony3控制檯運行控制檯命令
- 22. 如何測試是否從CakePHP控制檯運行?
- 23. 如何從python運行和控制命令行程序?
- 24. 從cmd.exe運行時,基於C的控制檯應用程序崩潰,在VS2008調試器中運行良好?
- 25. 從CDrom運行Python程序
- 26. 從Python運行Java程序
- 27. 從ipython運行python程序
- 28. 從Erlang運行python程序
- 29. 無控制檯運行Win32程序「silient」
- 30. 保持運行C++程序控制臺?
所以你不想使用命令行,而且你不想編輯源代碼......你還想過其他什麼方式? – Amber