在创建与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,特别是没有多处理。
答案 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
。然而,在您感到舒适使用之前,您可能需要研究一段时间。