2017-09-16 51 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