Это вопрос из двух частей. Во-первых, как правильно закрыть соединение с urllib2? Я видел несколько примеров, и я принял лучшее решение, которое я мог найти. Однако при закрытии файлов возникает проблема.
В настоящее время я использую закрытие contextlib () следующим образом:
try:
with closing(self.opener.open(self.address,
None,
self.timeout)) as page:
self.data = page.read()
except:
# bail out..
Тем не менее, я все еще получаю ошибку «слишком много открытых файлов» после долгого времени на OSX. Я использовал ulimit для увеличения файлов до 2000 и выше. Я также установил максимальные файлы ядра до> 40000. Должен заметить, что объект, к которому относится этот метод, не утилизируется и остается на всю жизнь программы. Однако я сохраняю только «данные», хранящиеся в объекте, а также адрес и время ожидания. Я не храню файловый объект. Я думал, что проблема может быть в ссылках, но я не верю в это, потому что я никогда не храню ссылку на файловый объект напрямую, только данные из read (). Эти объекты повторно используются и загружаются с новыми данными каждый раз, когда поток извлекает URL-адрес из очереди.
Я открываю только около 50 соединений одновременно. Я не совсем понимаю, как у меня закончились файлы. Кроме того, когда у меня заканчиваются файлы, netstat начинает выдавать ошибки malloc:
netstat(439) malloc: *** mmap(size=18446744073708605440) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
netstat: malloc 18446744073708605396 bytes: Cannot allocate memory
Я также не могу найти способ сбросить соединения и вернуть netstat в нормальное состояние без выключения.
netstat -m
$ netstat -m
475/3803 mbufs in use:
475 mbufs allocated to data
3328 mbufs allocated to caches
407/3814 mbuf 2KB clusters in use
0/577 mbuf 4KB clusters in use
0/12 mbuf 16KB clusters in use
11242 KB allocated to network (8.3% in use)
0 requests for memory denied
0 requests for memory delayed
0 calls to drain routines
У меня возникают проблемы с обнаружением ошибки, но я считаю, что соединения не закрываются своевременно, и я хорошо знаю, что соединения не используются повторно даже при подключении к одному домену (мне бы этого хотелось). Это вторая часть вопроса. Как кто-то может повторно использовать соединение с urllib2?
У меня есть несколько потоков, получающих URL-адреса из очереди, и каждый получает данные с помощью такой процедуры. Если возможно, я бы хотел повторно использовать соединение, если оно было открыто другим потоком. Единственными данными, которыми обмениваются потоки, является очередь URL. Я посмотрел на другие модули, но они, кажется, нуждаются в большем обмене данными, чем просто URL.