2017-02-03 40 views
0

該程序檢查url是否導致404,如果有,它會將用戶名寫入文件。我試圖添加多處理,以便程序運行得更快,因爲有些時候我會用1000行的文本文件輸入文本文件,這需要很長時間。但是,我第一次運行這個程序(當輸出文本文件爲空時),它不會向輸出文本文件寫入任何內容。它只能在第2,3,4 ...次運行時開始寫入輸出文件。程序只在第一個程序後的運行中寫入文件

#program checks twitch accounts in a file. 
#writes accounts which aren't taken to another file. 
import requests 
from multiprocessing import Pool 
x = "0" 

accounts = open('accounts.txt', 'r') 
valid_accounts = open('valid accounts.txt', 'a') 

base_url = "https://www.twitch.tv/" 

def check(x): 
    for line in accounts: 
     url = base_url + line 
     twitch_r = requests.get(url) 
     if twitch_r.status_code == 404: 
      valid_accounts.write(line + "\n") 



def Main(): 
    p = Pool(processes=25) 
    p.imap(check, x) 
    accounts.close() 
    valid_accounts.close() 



if __name__ == "__main__": 
    Main() 

回答

0

你的主要問題是,你使用imap,而不是mapimap是非阻塞的,這意味着您的主進程在進程運行之前退出。我有點驚訝,它的工作有時,因爲我認爲它應該工作從來沒有

這就是說,有幾個問題,你的程序:

  • 的檢查方法,在不同的進程中運行,股較行一個文件處理程序和迭代。這只是偶然的工作(例如,它不會在Windows上工作),並且是不好的做法(把它放在中間)。您應該首先讀取文件,然後將這些行分配給進程
  • 對寫入文件同樣適用。雖然追加到一個文件是安全的也跨越進程,但更好的設計將把它放在父進程末尾
  • mapimap被認爲運行在參數列表上,然後返回結果(映射值)
  • 離開了processes=20所以Python可以找出進程的最佳數量的基礎上基於這些東西你的電腦有多少個核具有

,這是代碼,我建議:

# program checks twitch accounts in a file. 
# writes accounts which aren't taken to another file. 
import requests 
from multiprocessing import Pool, Queue 

base_url = "https://www.twitch.tv/" 

def check(line): 
    twitch_r = requests.get(base_url + line) 
    if twitch_r.status_code == 404: 
     return line 

def Main(): 
    queue_in = Queue() 
    queue_out = Queue() 
    p = Pool() 

    with open('accounts.txt', 'r') as accounts: 
     lines = accounts.readlines() 

    results = p.map(check, lines) 
    results = [r for r in results if r != None] 
    with open('valid accounts.txt', 'a') as valid_accounts: 
     for result in results: 
      valid_accounts.write(result) 

if __name__ == "__main__": 
    Main() 

唯一要注意的是,您需要刪除Noneresults,因爲check(line)返回None所有的結果都不是404的網址。

更新

用約翰的解決方案之後,該程序正在按預期

我懷疑它。由於你在windows上,每個進程都有它自己的文件處理程序,指向accounts.txt,並且將遍歷所有行。所以,你最終20次檢查每個URL和多不伺候你

我使用IMAP,因爲我讀了IMAP不返回一個列表(?)

號地圖的與IMAP在這種情況下,所不同的僅僅是地圖等待,直到所有工序均由內部完成(因此,你不需要調用join)。

關於地圖vs imap的更全面討論see here

+0

使用John的解決方案後,該程序按預期工作。在我改變任何東西之前,它正在Windows上的第一個之後運行。我同意你的看法,我應該首先閱讀這些句子,然後將其發送給池中的參數,但我不知道如何使它成爲每個進程都有不同的參數。如果我爲文件中的每一行創建for循環,我將使用line作爲我的pool函數的參數,所以如果我沒有錯,每個進程都會使用相同的參數。我使用了imap,因爲我讀到imap不返回列表(?)。 404是對的。 – abc12333333

+0

@ abc12333333如果您要使用map並使其成爲「每個進程採用不同的參數」,請查看我的解決方案。這正是它所做的。 map從'lines'獲取一個值,然後將其映射到'results'中,然後將'return'存儲在'results'中。這是並行完成的 – hansaplast

+0

@ abc12333333您的其他問題我添加到我的答案。關於404:我現在改變了它,所以它做你想做的。請嘗試我上面的解決方案,它應該工作,它在我的機器上工作 – hansaplast

0

你應該在Main()末調用p.close()然後p.join()

+0

修正了這個問題。我明白,當我不再使用池時會使用close函數,但我不確定連接函數的作用。從我可以收集的內容來看,連接函數等待工作進程終止,但是我的代碼不應該在終止後立即完成嗎?有什麼等待? – abc12333333

+0

@ abc12333333'join()'等待所有進程完成。上面的程序啓動進程並立即退出,並使進程死亡 – hansaplast

0

你是不是通過你的帳戶池地圖

p.imap(check, accounts) 
+0

我認爲我對它編碼不好,但是在上面發佈的代碼中傳遞給我的pool.imap的代碼只是隨機的,因爲我需要一個參數。檢查功能本身是從文件中獲取帳戶。 – abc12333333