程序无法退出。如何查找Python正在做什么?
我有一个Python脚本,目前运行得很好。不过,我发现我的程序没有正常退出。我可以调试到最后,但程序还是一直在运行。
main.main()这个函数做了很多事情:它从数据提供者那里下载一些CSV文件(支持http、ftp、sftp等),把数据转换成标准格式,然后把所有内容加载到数据库里。
这一切都运行得很顺利。但是,程序就是不退出。我该怎么找出程序在哪里“等待”呢?
有多个数据提供者,这个脚本对所有提供者都能正常结束,只有一个(sftp下载,我用的是paramiko)不行。
if __name__ == "__main__":
main.log = main.log2both
filestoconvert = []
#filestoconvert = glob.glob(r'C:\Data\Feed\ProviderName\download\*.csv')
main.main(['ProviderName'], ['download', 'convert', 'load'], filestoconvert)
我很乐意听听大家的想法和建议!
5 个回答
你最好使用 GDB,它可以帮助你找到卡住的程序,就像Java中的jstack一样。
这个问题虽然已经有10年了,但我还是想分享我的解决方案,希望能帮助到遇到类似问题的人,尤其是那些Python脚本一直不结束的情况。
在我的情况下,调试过程并没有什么帮助。所有的调试输出只显示了一个线程。但是@JC Plessis的建议让我意识到,可能还有其他工作在进行,这让我找到了问题的根源。
我当时在用Selenium和Chrome驱动,关闭唯一打开的标签页后,我就结束了selenium的进程,代码是这样的:
driver.close()
但后来,我把代码改成了使用无头浏览器(也就是没有界面的浏览器),结果在调用driver.close()
后,Selenium驱动并没有关闭,导致Python脚本一直卡在那里。经过查找,我发现正确关闭Selenium驱动的方法其实是:
driver.quit()
这样做后,问题就解决了,脚本终于又能正常结束了。
如果你的程序没有结束,最有可能的原因是还有一个线程在运行。
要查看所有正在运行的线程,你可以使用:
threading.enumerate()
这个函数会列出所有当前正在运行的线程(详细信息可以查看文档)。
如果这还不够,你可能需要写一点脚本来配合这个函数(详细信息可以查看文档):
sys._current_frames()
所以,要打印所有活跃线程的堆栈信息,你可以这样做:
import sys, traceback, threading
thread_names = {t.ident: t.name for t in threading.enumerate()}
for thread_id, frame in sys._current_frames().iteritems():
print("Thread %s:" % thread_names.get(thread_id, thread_id))
traceback.print_stack(frame)
print()
祝你好运!