2013-03-26 70 views
4

我想在python3.3中實現一個服務器,它有一個單獨的線程預先加載來爲傳入連接執行所有處理。多處理python-server創建太多臨時目錄

from multiprocessing import Process, Pipe, Queue 
from multiprocessing.reduction import reduce_socket 
import time 
import socketserver,socket 


def process(q): 
    while 1: 
     fn,args = q.get() 
     conn = fn(*args) 

     while conn.recv(1, socket.MSG_PEEK): 
      buf = conn.recv(100) 
      if not buf: break 
      conn.send(b"Got it: ") 
      conn.send(buf) 

     conn.close() 

class MyHandler(socketserver.BaseRequestHandler): 
    def handle(self): 
     print("Opening connection") 
     print("Processing") 
     self.server.q.put(reduce_socket(self.request)) 
     while self.request.recv(1, socket.MSG_PEEK): 
      time.sleep(1) 
     print("Closing connection") 

class MyServer(socketserver.ForkingTCPServer): 
    p = Process 
    q = Queue() 
    parent_conn,child_conn = Pipe() 
    def __init__(self,server_address,handler): 
     socketserver.ForkingTCPServer.__init__(self,server_address, handler) 
     self.p = Process(target=process,args=(self.q,)) 
     self.p.start() 
    def __del__(self): 
     self.p.join() 


server_address = ('',9999) 
myserver = MyServer(server_address,MyHandler) 
myserver.serve_forever() 

我可以測試它的工作原理使用下面的腳本:

from multiprocessing.reduction import reduce_socket 
import time 
import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect(('localhost', 9999)) 

time.sleep(1) 
print("reduce_socket(s)") 
fn,args = reduce_socket(s) 
time.sleep(1) 
print("rebuild_socket(s)") 
conn = fn(*args) 
time.sleep(1) 
print("using_socket(s)") 

conn.send("poks") 
print conn.recv(255) 
conn.send("poks") 
print conn.recv(255) 
conn.send("") 
print conn.recv(255) 
conn.close() 

遺憾的是,似乎有什麼東西,因爲運行了n次測試後,我的TMP文件夾中充滿了這是錯誤的子文件夾:

$ ls /tmp/pymp*|wc -l 
32000 

這些臨時文件由socket_reduce()創建。有趣的是,客戶端中的rebuild/reduce_socket()也創建臨時文件,但是一旦函數退出,它們就會被刪除。我目前的tmp-filesystem文件夾的最大數量是32000,這會導致問題。我可以手動或在服務器的某個地方刪除/ tmp/pymp *文件,但我想應該也有正確的方法來做到這一點。誰能幫我這個?

+0

我沒有看到您的代碼中將創建一個臨時文件。這些子文件夾從哪裏來? – Pace 2013-03-26 13:43:04

+0

對不起。它是創建它們的socket_reduce()。 – 2013-03-26 14:15:40

+1

從你發佈的代碼看來,你永遠不會做一個'rebuild_socket',這會導致臨時文件掛起,因爲沒有聲明它們。 – Wessie 2013-03-26 14:34:35

回答

0

好的,有點固定它。來自 。 ./lib/python3.3/multiprocessing/util.py:

$ grep "def get_temp_dir" -B5 /usr/local/lib/python3.3/multiprocessing/util.py 

# 
# Function returning a temp directory which will be removed on exit 
# 

def get_temp_dir(): 

看來,臨時目錄應可直到進程退出。由於我的process()main()都運行永久,臨時文件將不會被刪除。要解決它,我可以創建另一個進程,將手中的reduced_socket到process()

def process(q): 
    while 1: 
     fn,args = q.get() 
     conn = fn(*args) 

     while conn.recv(1, socket.MSG_PEEK): 
      buf = conn.recv(100) 
      if not buf: break 
      conn.send(b"Got it: ") 
      conn.send(buf) 

     conn.close() 
     q.put("ok") 



class MyHandler(socketserver.BaseRequestHandler): 
    def socket_to_process(self,q): 
     q.put(reduce_socket(self.request)) 
     q.get() 
    def handle(self): 
     p = Process(target=self.socket_to_process,args=(self.server.q,)) 
     p.start() 
     p.join() 

這樣的子進程將退出,一旦process()已經做了的事情與輸入創建的臨時文件。我不認爲這是一個很好的方式,但它的工作原理。如果有人知道更好,請讓stackoverflow知道。