2013-03-11 66 views
0

我正在使用python线程来解析网站IP地址。这是我解决问题的工作流程。这是一个守护线程。Python线程似乎冻结了机器

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() 

编辑:域= domains_q.get()这条线块,直到产品在队列可用

问题是当我在300个线程运行此,平均负载似乎不错,但简单的LS -la需要5秒,一切都是缓慢的。我哪里做错了?我应该使用异步还是多处理?

+0

你确定空队列异常被打破循环? – andsoa 2013-03-11 15:39:42

+0

domains_q.get()此行会阻止,直到某个项目可用,我已将其添加到帖子中。 – nacholibre 2013-03-11 15:45:35

回答

0

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

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

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