2012-12-31 91 views
1

我是python的新手,嘗試同時執行兩個任務。這些任務只是在Web服務器上獲取頁面,並且可以在另一個之前終止。我只想在服務完所有請求後才顯示結果。在linux shell中很容易,但是我無法使用python,所有的howto對於像我這樣的初學者來說都像黑魔法一樣。與下面的bash腳本的簡單性相比,它們都讓我看起來很複雜。Python中的簡單多線程

這裏是bash腳本,我想在python效仿:

# First request (in background). Result stored in file /tmp/p1 
wget -q -O /tmp/p1 "http://ursule/test/test.php?p=1&w=5" & 
PID_1=$! 

# Second request. Result stored in file /tmp/p2 
wget -q -O /tmp/p2 "http://ursule/test/test.php?p=2&w=2" 
PID_2=$! 

# Wait for the two processes to terminate before displaying the result 
wait $PID_1 && wait $PID_2 && cat /tmp/p1 /tmp/p2 

test.php的腳本是一個簡單的:

<?php 
printf('Process %s (sleep %s) started at %s ', $_GET['p'], $_GET['w'], date("H:i:s")); 
sleep($_GET['w']); 
printf('finished at %s', date("H:i:s")); 
?> 

的bash腳本返回以下:

$ ./multiThread.sh 
Process 1 (sleep 5) started at 15:12:59 finished at 15:12:04 
Process 2 (sleep 2) started at 15:12:59 finished at 15:12:01 

我到目前爲止在python 3中試過的東西:

#!/usr/bin/python3.2 

import urllib.request, threading 

def wget (address): 
    url = urllib.request.urlopen(address) 
    mybytes = url.read() 
    mystr = mybytes.decode("latin_1") 
    print(mystr) 
    url.close() 

thread1 = threading.Thread(None, wget, None, ("http://ursule/test/test.php?p=1&w=5",)) 
thread2 = threading.Thread(None, wget, None, ("http://ursule/test/test.php?p=1&w=2",)) 

thread1.run() 
thread2.run() 

像預期的那樣返回這不起作用:

$ ./c.py 
Process 1 (sleep 5) started at 15:12:58 finished at 15:13:03 
Process 1 (sleep 2) started at 15:13:03 finished at 15:13:05 
+3

你想'thread1.start(); thread2.start()'然後'join'。有關線程模塊的基本信息,請參閱http://docs.python.org/2/library/threading.html。現在,線程不會複製您與Bash的行爲。爲此,您將需要多個進程,並且您應該檢查多處理模塊http://docs.python.org/2/library/multiprocessing.html – mmgp

+0

它似乎與join一起工作正常。我會看看多處理。感謝您讓我走上正軌。 – ripat

回答

1

而不是使用線程的,這將是很好使用多模塊作爲相互獨立的任務。您可能想了解更多關於GIL的信息(http://wiki.python.org/moin/GlobalInterpreterLock)。

0

按照你的建議,我跳入有關多線程和多處理的文檔頁面,在做了幾個基準測試後,我得出了多處理更適合這項工作的結論。隨着線程/進程數量的增加,它會更好地擴展。我面臨的另一個問題是如何存儲所有這些過程的結果。使用Queue.Queue做了訣竅。這裏是我想出的解決方案:

這段代碼發送併發http請求到我的測試平臺,在發送anwser之前暫停一秒鐘(請參閱上面的php腳本)。

import urllib.request 

# function wget arg(queue, adresse) 
def wget (resultQueue, address): 
    url = urllib.request.urlopen(address) 
    mybytes = url.read() 
    url.close() 
    resultQueue.put(mybytes.decode("latin_1")) 

numberOfProcesses = 20 

from multiprocessing import Process, Queue 

# initialisation 
proc = [] 
results = [] 
resultQueue = Queue() 

# creation of the processes and their result queue 
for i in range(numberOfProcesses): 
    # The url just passes the process number (p) to the my testing web-server 
    proc.append(Process(target=wget, args=(resultQueue, "http://ursule/test/test.php?p="+str(i)+"&w=1",))) 
    proc[i].start() 

# Wait for a process to terminate and get its result from the queue 
for i in range(numberOfProcesses): 
    proc[i].join() 
    results.append(resultQueue.get()) 

# display results 
for result in results: 
    print(result)