如何使用Multiprocessing创建nntplib对象

时间:2017-09-16 16:27:11

标签: python python-3.x python-multiprocessing

在创建与NNTP服务器的连接时尝试2天以使多处理工作正常。目标:尽可能快地建立一堆连接(如50)。由于在for循环中建立连接速度很慢(比如高达10秒),我想立即将它们全部制作出来#39;使用多处理。在创建连接之后,它们仍然是开放的,因为将来会在未来的多处理部分中提出10,000多个请求,依赖于类似的原则。

代码的一些简化部分:

#!/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,特别是没有多处理。

1 个答案:

答案 0 :(得分:2)

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

即使它有效,.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。然而,在您感到舒适使用之前,您可能需要研究一段时间。