2017-09-16 54 views
1

在创建到NNTP服务器的连接时尝试2天才能使多重处理工作。目标:尽可能快地建立一堆连接(如50)。由于在for循环中连接速度可能会很慢(比如高达10秒),所以我希望使用多处理功能将它们全部“一次”完成。在建立连接之后,它们保持开放状态,因为在将来的多处理部分中将有10,000多个请求依赖于类似的原理。如何使用多重处理创建nntplib对象

代码的一些简单的部分:

#!/usr/bin/env python3 

import sys 
import ssl 
from nntplib import NNTP_SSL 
from multiprocessing import Pool 

def MakeCon(i, host, port): 
    context = ssl.SSLContext(ssl.PROTOCOL_TLS) 
    s = NNTP_SSL(host, port=port, ssl_context=context, readermode=True) 
    print('created connection', i) # print to see progress 
    sys.stdout.flush() 
    return s 

def Main(): 
    host = 'reader.xsnews.nl' 
    port = 563 
    num_con = 4 

    y=MakeCon(1, host, port).getwelcome() #request some message from NNTP host to see if it works 
    print(y) 

    # the actual part that has the issue: 
    if __name__ == '__main__': 

     cons = range(num_con) 
     s = [None] * num_con 
     pool = Pool() 
     for con in cons: 
      s[con]=pool.apply_async(MakeCon, args=(con, host, port)) 
     pool.close 

     print(s[1]) 
     for con in cons: 
      t=s[con].getwelcome() #request some message from NNTP host to see if it works 
      print(t) 

     print('end') 

Main() 

显示的是到NNTP服务器等的连接工作,但我在部分无法提取连接到某个对象,我可以结合的nntplib使用选项。我会说我不是那种经验丰富的Python,特别是不是多处理。

+0

您是否试图创建到同一个新闻服务器的多个连接? – JohanL

+0

@JohanL谢谢,是的,尽可能快,所以我不太喜欢NNTP_SSL()/ NNTP(),因为每次在建立连接之前可能有1秒的等待时间。这就是为什么我想使用多处理技术“同时”创建它们。 – uytda

回答

1

您的方法有几个不同的问题。最大的问题是它不能在不同的流程中创建连接,然后将它们发送到主流程。这是因为每个连接都会打开一个套接字,套接字不可序列化(可选),因此不能在进程之间发送。

即使它已经工作,使用.apply_sync()是不正确的路要走。最好使用.map(),它直接返回函数调用的输出(而不是返回可以提取返回值的对象的.apply_sync())。

但是,在当前情况下,程序是I/O绑定的,而不是CPU绑定的,在这些情况下,线程工作和多处理一样好,因为GIL不会阻止执行。因此,改变线程,而不是多和.map().apply_sync()给出了以下解决方案:

#!/usr/bin/env python3 

import sys 
import ssl 
from nntplib import NNTP_SSL 
from multiprocessing.pool import ThreadPool 

def MakeCon(i, host, port): 
    context = ssl.SSLContext(ssl.PROTOCOL_TLS) 
    s = NNTP_SSL(host, port=port, ssl_context=context, readermode=True) 
    print('created connection', i) # print to see progress 
    sys.stdout.flush() 
    return s 

def Main(): 
    host = 'reader.xsnews.nl' 
    port = 563 
    num_con = 4 

    y=MakeCon(1, host, port).getwelcome() #request some message from NNTP host to see if it works 
    print(y) 
    return con 

    cons = range(num_con) 
    s = [None] * num_con 
    pool = ThreadPool() 
    s=pool.map(lambda con: MakeCon(con, host, port), cons) 
    pool.close 

if __name__ == "__main__": 
    Main() 

咨询的小词,但。注意创建太多的连接,因为从服务器上查看可能不太合适,因为您正在耗尽资源。另外,如果您要使用不同的连接来获取文章,这些调用应该也可能在不同的线程中完成。

而且,作为最终评论,与使用线程相同的效果是使用asyncio。然而,这是你可能需要研究一段时间,然后才能感觉舒适。

+0

套接字工作得很好,而且速度更快。我使用相同的原则为创建的套接字通过函数check_id()请求头,以循环列表“ids”:'j = itertools.cycle(range(len(socks)))',接着是't = pool。 map(lambda id:check_id(socks,next(j),id),ids)'这种方法对于4个套接字比1稍快,但是对于10来说没有增益。 (服务器的ping和延迟非常低)。猜测循环方法会阻止它,因为典型的套接字尚未释放。 (在我使用'socket' I/o'nntplib'之前,为了避免'asyncio'做了很多循环) – uytda