2015-03-13 51 views
6

我写了一个简单的脚本,它使用线程从服务中检索数据。有异常错误“线程线程-13中的异常(最有可能在解释器关闭期间引发)”

__author__ = 'Igor' 
import requests 
import time 
from multiprocessing.dummy import Pool as ThreadPool 

ip_list = [] 
good_ip_list = [] 
bad_ip_list = [] 
progress = 0 

with open('/tmp/ip.txt') as f: 
    ip_list = f.read().split() 

def process_request(ip): 
    global progress 
    progress += 1 
    if progress % 10000 == 0: 
     print 'Processed ip:', progress, '...' 
    r = requests.get('http://*****/?ip='+ip, timeout=None) 
    if r.status_code == 200: 
     good_ip_list.append(ip) 
    elif r.status_code == 400: 
     bad_ip_list.append(ip) 
    else: 
     print 'Unknown http code received, aborting' 
     exit(1) 

pool = ThreadPool(16) 
try: 
    pool.map(process_request, ip_list) 
except: 
    for name, ip_list in (('/tmp/out_good.txt', good_ip_list),  ('/tmp/out_bad.txt', bad_ip_list)): 
     with open(name, 'w') as f: 
      for ip in ip_list: 
       print>>f, ip 

但经过一些请求处理(40K-50K)我得到:螺纹加工-7

异常(解释关闭过程中最有可能提出的): 回溯(最近通话最后一个): 过程完成了退出代码0

尝试变更服务设置:

 <timeout>999</timeout> 
     <connectionlimit>600</connectionlimit> 
     <httpthreads>32</httpthreads> 
     <workerthreads>128</workerthreads> 

但还是同样的错误。任何人都可以帮助我 - 怎么了?

+0

'打印> > f,ip'这是一个错字?追溯中还有其他什么吗? – 2015-03-13 08:21:26

+1

'进步+ = 1'在语言与可变数据和使用多线程W/O任何保护...我停止看这一点;) – iced 2015-03-13 08:22:40

+1

@PatrickCollins正如我所理解的 - 在requests.exceptions.ConnectionError引发问题,尝试以捕获它并继续pool.map但效果相同 – Igor 2015-03-13 08:34:05

回答

4

感谢大家,谁帮我解决了这个问题。重写整个代码,现在,它完美的作品:

__author__ = 'kulakov' 
import requests 
import time 
from multiprocessing.dummy import Pool as ThreadPool 

ip_list = [] 
good_ip_list = [] 
bad_ip_list = [] 

with open('/tmp/ip.txt') as f: 
    ip_list = f.read().split() 

s = requests.Session() 
def process_request(ip): 
    r = s.get('http://*****/?ip='+ip, timeout=None) 
    if r.status_code == 200: 
     # good_ip_list.append(ip) 
     return (ip, True) 
    elif r.status_code == 400: 
     # bad_ip_list.append(ip) 
     return (ip, False) 
    else: 
     print 'Unknown http code received, aborting' 
     exit(1) 

pool = ThreadPool(16) 
for ip, isOk in pool.imap(process_request, ip_list): 
    if isOk: 
     good_ip_list.append(ip) 
    else: 
     bad_ip_list.append(ip) 
pool.close() 
pool.join() 

for name, ip_list in (('/tmp/out_good.txt', good_ip_list), ('/tmp/out_bad.txt', bad_ip_list)): 
    with open(name, 'w') as f: 
     for ip in ip_list: 
      print>>f, ip 

一些新的有用的信息:

1)这是非常糟糕的主意在功能process_request写在不同的线程的数据,现在它返回语句(真\ false)和ip。

2)keep aliverequests完全支持,默认情况下,但如果你想使用它,你必须创建一个对象Session的实例,并应用get方法只有它:

s = requests.Session() 
r = s.get('http://*****/?ip='+ip, timeout=None) 
1

此:

good_ip_list = [] 
bad_ip_list = [] 

是不是安全使用Python多重混合。正确的做法是从每次调用返回一个元组(或其他)到process_request,然后在最后连接它们。从多个进程同时修改progress也不安全。我不太确定你的错误是什么,但我敢打赌,这是一个同步问题,它将整个Python作为一个整体。

删除共享状态并重试。

+1

谢谢,@Patrick柯林斯 我想你是对这个建议: “我敢打赌这是杀害Python作为一个整体的一些同步问题” 你能解释一下多一点位,请了这一点: “删除共享状态,然后再试一次。“ 作为输入数据我有一个函数'process_request'和一个列表'ip_list'。 那么什么是正确的方式来映射这两个对象不是在循环(因为我试图用循环它完美的工作,但非常缓慢),但在不同的线程。 谢谢。 – Igor 2015-03-13 08:54:51

+1

@Igor在'process_request'内取出对'good_ip_list,bad_ip_list'和'progress'的引用。除了'process_request'内创建的对象之外,不要修改'process_request'内的任何内容。相反,请根据IP是否良好来做一些事情,例如在呼叫中返回“true”或“false”。 – 2015-03-13 09:00:00