2009-07-18 18 views
8

छोड़ने से ऐप को रोकता है मैंने एक बहुत ही सरल पायथन क्लास लिखा है जो सॉकेट पर कनेक्शन की प्रतीक्षा करता है। इसका उद्देश्य इस वर्ग को मौजूदा ऐप में रखना और असीमित रूप से ग्राहकों को जोड़ने के लिए डेटा भेजना है।पायथन सॉकेट ब्लॉक स्वीकार करते हैं -

समस्या यह है कि सॉकेट.एसेप्ट() पर प्रतीक्षा करते समय, मैं ctrl-c दबाकर अपना आवेदन समाप्त नहीं कर सकता। न तो मैं यह पता लगा सकता हूं कि मेरी कक्षा गुंजाइश से बाहर हो जाती है और इसे समाप्त करने के लिए सूचित करती है।

आदर्श रूप से नीचे दिए गए आवेदन को समय के बाद छोड़ना चाहिए। नींद (4) समाप्त हो जाती है। जैसा कि आप नीचे देख सकते हैं, मैंने चयन का उपयोग करने का प्रयास किया, लेकिन यह ऐप को ctrl-c का जवाब देने से रोकता है। अगर मैं पता लगा सकता हूं कि चर 'ए' मुख्य विधि में दायरे से बाहर हो गया है, तो मैं छोड़ने वाला ध्वज सेट कर सकता हूं (और इसे उत्तरदायी बनाने के लिए चयन पर टाइमआउट को कम कर सकता हूं)।

कोई विचार?

धन्यवाद


import sys 
import socket 
import threading 
import time 
import select 

class Server(threading.Thread): 
    def __init__(self, i_port): 
     threading.Thread.__init__(self) 
     self.quitting = False 
     self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.serversocket.bind((socket.gethostname(), i_port)) 
     self.serversocket.listen(5) 
     self.start() 

    def run(self): 
     # Wait for connection 
     while not self.quitting: 
      rr,rw,err = select.select([self.serversocket],[],[], 20) 
      if rr: 
       (clientsocket, address) = self.serversocket.accept() 
       clientsocket.close() 

def main(): 
    a = Server(6543) 
    time.sleep(4) 

if __name__=='__main__': 
    main() 

उत्तर

9

__init__ करने के लिए self.setDaemon(True)self.start() से पहले जोड़ें।

(पायथन 2.6 और बाद में, self.daemon = True को प्राथमिकता दी जाती है)।

कुंजी विचार here समझाया गया है:

पूरे अजगर कार्यक्रम छोड़कर चला जाता कोई जिंदा गैर डेमॉन धागे छोड़ दिया जाता है।

तो, आपको उन धागे के "डिमन्स" बनाने की ज़रूरत है जिन्हें पूरी जिंदा रहने से पूरी प्रक्रिया को जीवित नहीं रखना चाहिए। मुख्य धागा हमेशा से गैर-डिमन है।

+0

इसके लिए धन्यवाद, यह चाल है। मैंने self.daemon = True की कोशिश की लेकिन उसने कुछ भी नहीं किया (मैं Win32 पर पायथन 2.5 चला रहा हूं)। इसे self.setDaemon (True) में बदलना यद्यपि चाल था! धन्यवाद! –

4

मैं सामान्य शटडाउन के लिए setDememon सुविधा की अनुशंसा नहीं करता हूं। यह मैला है; धागे के लिए एक साफ शटडाउन पथ होने के बजाय, यह केवल थ्रेड को मारने के लिए बिना किसी मौके के मारता है। इसे सेट करना अच्छा होता है, इसलिए यदि आपका मुख्य थ्रेड अप्रत्याशित रूप से बाहर निकलता है तो आपका प्रोग्राम फंस नहीं जाता है, लेकिन यह त्वरित हैक्स को छोड़कर एक अच्छा सामान्य शटडाउन पथ नहीं है।

import sys, os, socket, threading, time, select 

class Server(threading.Thread): 
    def __init__(self, i_port): 
     threading.Thread.__init__(self) 
     self.setDaemon(True) 
     self.quitting = False 
     self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.serversocket.bind((socket.gethostname(), i_port)) 
     self.serversocket.listen(5) 
     self.start() 

    def shutdown(self): 
     if self.quitting: 
      return 

     self.quitting = True 
     self.join() 

    def run(self): 
     # Wait for connection 
     while not self.quitting: 
      rr,rw,err = select.select([self.serversocket],[],[], 1) 
      print rr 
      if rr: 
       (clientsocket, address) = self.serversocket.accept() 
       clientsocket.close() 

     print "shutting down" 
     self.serversocket.close() 

def main(): 
    a = Server(6543) 
    try: 
     time.sleep(4) 
    finally: 
     a.shutdown() 

if __name__=='__main__': 
    main() 

ध्यान दें कि यह बंद() है, जो गरीब व्यवहार है बुला के बाद एक दूसरा अप करने के लिए के लिए विलंब होगा। यह सामान्य रूप से ठीक करना आसान है: एक वेकअप पाइप() बनाएं जिसे आप लिख सकते हैं, और इसे चयन में शामिल कर सकते हैं; लेकिन हालांकि यह बहुत बुनियादी है, मुझे पाइथन में ऐसा करने का कोई तरीका नहीं मिला। (os.pipe() फ़ाइल डिस्क्रिप्टर लौटाता है, फाइल ऑब्जेक्ट्स नहीं जिन्हें हम लिख सकते हैं।) मैं गहरी खुदाई नहीं कर रहा हूं, क्योंकि यह सवाल के लिए स्पर्शपूर्ण है।

+0

आप os.fdopen के साथ एक पायथन फ़ाइल ऑब्जेक्ट में एक दायरस्क्रिप्टर को लपेट सकते हैं। लेकिन मैं इस बात से असहमत हूं कि थ्रेड में कोई विशेष सफाई की आवश्यकता नहीं होने पर सेटडेमॉन से ज्यादा कुछ भी जरूरी है - यह सिर्फ एक छोटी लेकिन डिस्पेंस करने योग्य जटिलता है। –

+0

मैंने इस तरह के एक दृष्टिकोण की कोशिश की - मेरी शटडाउन विधि बस एक इस्किटिंग ध्वज सेट करती है और सॉकेट से जुड़ी हुई है, जिससे स्वीकृति() कॉल को अनवरोधित कर दिया जाता है, जिससे धागे को छोड़ दिया जाता है। हालांकि यह शटडाउन() को कॉल करने वाले उपयोगकर्ता पर भरोसा करता है। फिर भी सुझाव के लिए धन्यवाद। –

+0

किसी साधारण हैक से बड़ा कुछ भी करने के लिए, आपको पूरी प्रक्रिया से बाहर निकलने के बिना थ्रेड को बंद करने में सक्षम होने की आवश्यकता होगी। यहां तक ​​कि "सफल शट डाउन" लॉग करना चाहते हैं, यहां तक ​​कि एक सरल सर्वर भी ऐसा करने की आवश्यकता होगी, या फिर भी शट डाउन लॉगिंग के बाद कनेक्शन स्वीकार कर लिया जाएगा। –

संबंधित मुद्दे