【问题标题】:Python multiprocess debuggingPython多进程调试
【发布时间】:2012-06-21 18:56:48
【问题描述】:

我正在尝试调试一个简单的 python 应用程序,但到目前为止还没有成功。

import multiprocessing

def worker(num):
    for a in range(0, 10):
        print a

if __name__ == '__main__':
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        p.start()

我想在 for 循环中设置一个断点来跟踪 'a' 的值,但我尝试过的工具都不能做到这一点。 到目前为止,我尝试使用以下方式进行调试:

  • PyCharm 并得到以下错误:ImportError: No module named pydevd - http://youtrack.jetbrains.com/issue/PY-6649 看起来像 他们仍在努力解决这个问题,据我了解,没有预计到达时间
  • 我也尝试使用 Winpdb 进行调试 - http://winpdb.org 但它根本不会进入我的“worker”方法,而只是打印“a”的值

非常感谢您对此的任何帮助!

【问题讨论】:

  • 说到多处理/多线程,没有“简单”之类的东西。在我看来,至少。
  • 这是 PyCharm 调试器中特定于 Windows 的错误。如果您确实需要使用多处理模块调试应用程序,我可以建议使用 Unix 虚拟机并从您的 PyCharm 为该 VM 设置远程解释器。跨度>

标签: python debugging multiprocessing pycharm winpdb


【解决方案1】:

你应该可以使用 remote-pdb 来做到这一点。

from multiprocessing import Pool


def test(thing):
  from remote_pdb import set_trace
  set_trace()
  s = thing*2
  print(s)
  return s



if __name__ == '__main__':
  with Pool(5) as p:
    print(p.map(test,['dog','cat','bird']))

然后只需 telnet 到日志中列出的端口。

例子:

RemotePdb session open at 127.0.0.1:54273, waiting for connection ...
telnet 127.0.0.1 54273
<telnet junk>
-> s = thing*2
(Pdb) 

nc -tC 127.0.0.1 54273

-> s = thing * 2
(Pdb)

此时您应该能够调试该进程。

【讨论】:

    【解决方案2】:

    我发现在设置断点时将multiprocessing.Process() 替换为threading.Thread() 非常有用。两个类都有相似的参数,所以在大多数情况下它们是可以互换的。

    通常我的脚本使用Process(),直到我指定命令行参数--debug,它有效地将这些调用替换为Thread()。这让我可以使用pdb 调试这些脚本。

    【讨论】:

      【解决方案3】:

      WingIDE Pro 提供开箱即用的此功能。

      不需要额外的代码(例如,使用traceback 模块)。您只需运行您的程序,Wing 调试器不仅会从子进程打印stdout,而且会中断子进程中的错误并立即创建一个交互式 shell,以便您可以调试有问题的线程 .没有比这更容易的了,而且我知道没有其他 IDE 以这种方式公开子进程。

      是的,它是一种商业产品。但是我还没有找到任何其他提供调试器来匹配的 IDE。 PyCharm Professional、Visual Studio Community、Komodo IDE——我都试过了。在我看来,WingIDE 在解析源文档方面也处于领先地位。而 Eye Ease Green 配色方案是我现在离不开的东西。

      (是的,我知道这个问题已有 5 年以上的历史了。无论如何我都会回答它。)

      【讨论】:

        【解决方案4】:

        如果常规 pdb/ipdb 可以与多处理一起使用,那就太好了。如果我能摆脱它,如果配置的进程数为 1,我会串行处理对多处理的调用。

        if processes == 1:
            for record in data:
                worker_function(data)
        else:
            pool.map(worker_function, data)
        

        然后在调试时,将应用程序配置为仅使用单个进程。这并不涵盖所有情况,尤其是在处理并发问题时,但它可能会有所帮助。

        【讨论】:

          【解决方案5】:

          我将 /Applications/PyCharm\ 2.6\ EAP.app/helpers/pydev/*.py 中的所有内容复制到了我的 virtualenv 中的 site-packages,它对我有用(我正在调试 celery/kombu,断点按预期工作)。

          【讨论】:

            【解决方案6】:

            在尝试调试 Python 代码时,我很少需要使用传统的调试器,而是更喜欢在我的代码中随意添加跟踪语句。我会将您的代码更改为以下内容:

            import multiprocessing
            import logging
            
            def worker(num):
                for a in range(0, 10):
                    logging.debug("(%d, %d)" % (num, a))
            
            if __name__ == '__main__':
                logging.basicConfig(level=logging.DEBUG)
                for i in range(5):
                    p = multiprocessing.Process(target=worker, args=(i,))
                    logging.info("Starting process %d" % i)
                    p.start()
            

            在生产中,您可以通过将跟踪级别设置为 logging.WARNING 来禁用调试跟踪语句,这样您就只记录警告和错误。

            Python 官方网站上有很好的 basicadvanced 日志记录教程。

            【讨论】:

            • 非常感谢您的快速回复,但不幸的是这不是我想要的。我应该在我的问题中提到的是,这只是我需要的功能的一个简单示例,但实际上我正在处理复杂的对象,我需要断点才能在特定时间查看它们的内容。简单地打印内容是不够的。
            • 我不知道有任何 Python 调试器能像 Visual Studio 调试器那样强大。也许您可以修改日志记录技术以仅在某些条件下记录,从而有效地模拟条件断点?
            • 日志记录很棒,但即使将日志记录级别设置为高于日志记录语句级别,它也不是免费的,因为函数调用在 Python 等动态语言中具有很高的成本。了解调试器是件好事,而且 pdb 随 Python 一起提供。那么这只是正确设置多处理项目的问题。
            • 在某些情况下,由于缓冲,您必须强制打印跟踪语句。
            • @cymruu 请参阅stackoverflow.com/a/230774/892327stackoverflow.com/a/230780/892327。缓冲通常对性能有好处,因此禁用它可能不是最好的主意。
            猜你喜欢
            • 1970-01-01
            • 2020-05-09
            • 2011-10-07
            • 2011-11-29
            • 1970-01-01
            • 1970-01-01
            • 2015-01-29
            • 2010-10-17
            • 1970-01-01
            相关资源
            最近更新 更多