2014-10-12 4 views
0

Мое текущее затруднительное положение состоит в том, что я попытался сделать блокирующий веб-сервисный скрипт не блокирующим, чтобы разрешить более одной загрузке в любой момент времени, но в настоящее время он будет зависать и ждать сначала загрузить, чтобы завершить, прежде чем начинать второй. Прежде чем вы уйдете с пути, чтобы проголосовать за это, потому что ответ одиозный, пожалуйста, знайте, что это мой первый сценарий python, и я сам преподаю.Почему мои потоки python блокируют друг друга

В приведенном ниже примере я только размещаете один «ConnectionProcesser» Потому что все они содержат один и тот же код если вам нужно больше кода, пожалуйста, просто спросить

Сценарий имеет 3 dependinces

import socket # Networking support 
import signal # Signal support (server shutdown on signal receive) 
import threading #to make the thing run more than one at a time 

Пожалуйста, обратите внимание, что сценарий был отредактирован, и совсем немного кода отсутствует, но я считаю, что он не связан с проблемой.

def ConnectionProcessorC(self): 
    connC, AddressC = self.socket.accept() 
    print("C Got connection from:", AddressC) 
    DataRecivedC = connC.recv(1024) #receive data from client 
    DataRecivedC = bytes.decode(DataRecivedC) #decode it to string 
    print(DataRecivedC) 
    RequestMethod = DataRecivedC.split(' ')[0] 
    print ("C Method: ", RequestMethod) 
    if (RequestMethod == 'GET') | (RequestMethod == 'HEAD'): 
     Response_Headers = 'HTTP/1.1 200 OK\n' 
     # Current_Date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) 
     # Response_Headers += 'Date: ' + current_date +'\n' 
     Response_Headers += 'Server: Moes-Python-Server\n' 
     Response_Headers += 'Connection: close\n\n' # signal that the conection wil be closed after complting the request 
     Server_Response = Response_Headers.encode() # return headers for GET and HEAD 
     file_handler = open('/usr/share/nginx/html/100mb.dump','rb') 
     Response_Content = file_handler.read() # read file content 
     file_handler.close() 
     URL=DataRecivedC.split(' ') 
     URL = URL[1] # get 2nd element 
     #Response_Content="<html><body><p>Charlie TEStin this stuff yehURL:"+URL+"</p></body></html>" 
     Server_Response += Response_Content 

     connC.send(Server_Response) 
     print ("C Closing connection with client") 
    else: 
     print("C Unknown HTTP request method:", RequestMethod) 

    connC.close() 
    return 
def Distrabuteconnections(self): 
    A=0 
    """ Main loop awaiting connections """ 
    while True: 
     print ("Awaiting New connection") 
     self.socket.listen(10) # maximum number of queued connections #changed to 1 from 3 to try and prevent waiting after closing for ther que to clean up 

     if (A==0): 
      ConnectionProcessorA = threading.Thread(target=self.ConnectionProcessorA()) 
      ConnectionProcessorA.start() 
      A=1 
     elif (A==1): 
      ConnectionProcessorB = threading.Thread(target=self.ConnectionProcessorB()) 
      ConnectionProcessorB.start() 
      A=2 
     else: 
      ConnectionProcessorC = threading.Thread(target=self.ConnectionProcessorC()) 
      ConnectionProcessorC.start() 
      A=0 

Я думаю, что проблема может быть решена путем изменения в то время как истина для чего-то, что петли 3 раза вместо одного.

+0

Переключение из потоков подпроцессов должен решить –

+0

Но зачем мне подпроцессов есть причина? и они не работают медленнее? – door

+0

Подпроцессы МОГУТ занять немного больше времени и иметь более высокий объем памяти, но нет причин, по которым они будут медленнее. И причиной будет GIL, который, кажется, вмешивается в потоки. Это не происходит в подпроцессах. –

ответ

0

Вы должны передать ссылку на метод, который хотите начать в потоке. Вместо этого вы вызываете поток и передаете данные, возвращенные этим методом, на вызов threading.Thread().

Короче код должен стать:

 if (A==0): 
     ConnectionProcessorA = threading.Thread(target=self.ConnectionProcessorA) 
     ConnectionProcessorA.start() 
     A=1 
    elif (A==1): 
     ConnectionProcessorB = threading.Thread(target=self.ConnectionProcessorB) 
     ConnectionProcessorB.start() 
     A=2 
    else: 
     ConnectionProcessorC = threading.Thread(target=self.ConnectionProcessorC) 
     ConnectionProcessorC.start() 
     A=0 

Примечания удаления скобок после self.ConnectionProcessorA и т.д. Это передает ссылку на метод, чтобы начать в потоке, который модуль потокового будет вызывать себя.

Примечание. Рекомендуется хранить ссылку на созданную вами нить, чтобы она не собирала мусор. Я бы таким образом рекомендовать ваш код становится:

 if (A==0): 
     self.cpa_thread= threading.Thread(target=self.ConnectionProcessorA) 
     self.cpa_thread.start() 
     A=1 
    elif (A==1): 
     self.cpb_thread= threading.Thread(target=self.ConnectionProcessorB) 
     self.cpb_thread.start() 
     A=2 
    else: 
     self.cpc_thread= threading.Thread(target=self.ConnectionProcessorC) 
     self.cpc_thread.start() 
     A=0 
+0

Я пробовал свой код, все, что он сделал, был запущен ConnectionProcessorA снова и снова, поэтому я не мог проверить, работает ли он или нет – door

+0

Я думаю мне нужно сделать это, чтобы удалить true и заменить его вызовом из потока, когда соединение создано, поэтому скрипт не просто продолжает создавать потоки, как сейчас. – door

+0

Я бы ожидал, что все 3 потока будут продолжать работать , но да, лучше всего просто создавать поток при каждом подключении. Потенциально вы могли бы вызвать 'socket.accept()' в основном потоке и передать переменные 'connX' и' AddressX' в поток. Если вам нужна помощь в изменении архитектуры вашей программы, лучше всего разместить новый вопрос с ** минималистическим рабочим примером ** того, что вы делаете сейчас, чтобы люди могли фактически запускать некоторый код, который имитирует то, что вы делаете. –