Python线程似乎冻结了机器

时间:2013-03-11 15:16:17

标签: python multithreading

我正在使用python线程来解析网站IP地址。这是我解决的工人流程。这是一个守护程序线程。

def get_ip_worker():
    """This is the worker (thread) process for parsing ips, this process takes domain from the q processes it
    and then saves it to another q"""

    socket.setdefaulttimeout(3)
    while True:
        domain = domains_q.get()
        try:
            addr_info = socket.getaddrinfo(domain, 80, 0, 0, socket.SOL_TCP)
            for family, socktype, proto, name, ip in addr_info:
                if family == 2: #okay it's ipv4
                    ip, port = ip
                    processed_q.put((ip, domain))
                elif family == 10: #okay it's ipv6
                    ip, port, no_1, no_2 = ip
                    processed_q.put((ip, domain))
        except:
            pass
            #print 'Socket Error'

        domains_q.task_done()

编辑:domain = domains_q.get()此行在队列中阻止项目可用

当我在300个线程上运行此问题时,Load Average似乎没问题,但简单的ls -la需要5秒,而且一切都很慢。我哪里做错了?我应该使用异步还是多处理?

1 个答案:

答案 0 :(得分:0)

你真的需要300个线程并行处理300个连接吗?我从未尝试过创建那么多线程,但这可能是个问题。这绝对不是解决问题的好方法。通常还有其他选择。首先,您不需要300个线程来侦听300个连接。创建一些似乎适用于您的硬件和操作系统的线程。使用单个线程从主队列中检索请求,然后将它们传递给thread pool的线程。

BTW,检查你的“从队列中检索”操作是否真的阻塞并等待队列为空。如果不是,则可以一直执行循环,而不是取决于是否有传入请求。

您可能真正需要的是套接字的非阻塞模式以及类似select.select()之类的东西,等待其中一个套接字准备好进行读取或写入。您可以自己编写该代码。如果您不急于这样做,那么像gevent(或twisted)这样的好的异步网络库可能有助于改进程序的体系结构。利用多核CPU的全部功能是一个单独的问题,但我听说有解决方案,至少对于gevent(它们基于运行多个进程的gunicorn;从未尝试过)。但我认为您遇到的问题不是执行速度,而是需要一次有效地等待许多对象的I / O.如果是这样,为了这个目的避免大量使用线程,它通常不仅在Python中有效,甚至在没有GIL的语言中更适合多线程编程。 multiprocessing避免了GIL,但增加了自己的执行成本,所以我建议不要在这里使用它。