2015-10-03 22 views
9

मुझे एक स्क्रिप्ट मिली है जो एक अनंत लूप पर चलती है और चीजों को डेटाबेस में जोड़ती है और ऐसी चीजें करता है जो मैं केवल आधे रास्ते से नहीं रोक सकता, इसलिए मैं सिर्फ ctrl + c दबा नहीं सकता और इसे रोक नहीं सकता।पायथन में सुरक्षित लूप को सुरक्षित रूप से कैसे रोकें?

मैं किसी भी तरह से लूप को रोकने में सक्षम होना चाहता हूं लेकिन इसे रोकने से पहले इसे अंतिम पुनरावृत्ति समाप्त करने दें।

मुझे स्पष्ट करते हैं:

while True: 
    does something 
    does more things 
    does more things 

मैं अंत में, जबकि पाश, या शुरुआत में दखल देने में सक्षम होना चाहते हैं, लेकिन काम करने की वजह से दोनों के बीच नहीं:

मेरे कोड कुछ इस तरह दिखता वह बुरा होगा।

और मैं नहीं चाहता कि मैं इसे जारी रखने के लिए हर पुनरावृत्ति के बाद मुझसे पूछूं। महान जवाब के लिए

धन्यवाद, मैं सुपर आभारी हूँ, लेकिन मेरी कार्यान्वयन काम नहीं लगता है:

def signal_handler(signal, frame): 
     global interrupted 
     interrupted = True 

class Crawler(): 
    def __init__(self): 
    # not relevent 

    def crawl(self): 
     interrupted = False 
     signal.signal(signal.SIGINT, signal_handler) 
     while True: 
      doing things 
      more things 

      if interrupted: 
       print("Exiting..") 
       break 

बस मुझे

+0

क्या आपके पास अपनी स्क्रिप्ट में निर्धारित करने का कोई तरीका है कि यदि काम पूरा हो गया है (आखिरी एक)! यदि आप ऐसा करते हैं तो इसे किसी शर्त में उपयोग करें और ब्रेक स्टेटमेंट – praba230890

+0

का उपयोग करें इस मामले में नौकरी अनिश्चित काल तक जारी रखने की तुलना में एक वेब क्रॉलर है। मैं इसे क्रॉलिंग रोकने के लिए कहने में सक्षम होना चाहता हूं लेकिन उदाहरण के लिए इसे पृष्ठ के मध्य में बाधित न करें। – davegri

+0

* इसे रोकने से पहले इसे अंतिम पुनरावृत्ति खत्म करने दें *? आप कैसे जानते हैं कि उसने नौकरी की है या नहीं? –

उत्तर

9

क्या आप व्यवधान पकड़ने करने की जरूरत है, एक झंडा कह आप बाधित कर रहे थे लेकिन फिर से काम कर रहा है जब तक यह (प्रत्येक के अंत में ध्वज की जाँच करने का समय है जारी रखने के लिए सेट पाश)। चूंकि पाइथन की कोशिश-छोड़कर निर्माण लूप के वर्तमान भाग को छोड़ देगा, आपको उचित संकेत हैंडलर स्थापित करने की आवश्यकता है; यह बाधा को संभालेगा लेकिन फिर पाइथन जारी रखेगा जहां यह छोड़ा गया था। ऐसे करें:

import signal 

import time # For the demo only 

def signal_handler(signal, frame): 
    global interrupted 
    interrupted = True 

signal.signal(signal.SIGINT, signal_handler) 


interrupted = False 
while True: 
    print("Working hard...") 
    time.sleep(3) 
    print("All done!") 

    if interrupted: 
     print("Gotta go") 
     break 

नोट्स:

  1. कमांड लाइन से इस का प्रयोग करें। आईडीएलई कंसोल में, यह आईडीएलई के अपने इंटरप्ट हैंडलिंग पर टंपल करेगा।

  2. एक बेहतर समाधान लूप की अवधि के लिए कीबोर्ड अवरोध को "ब्लॉक" करना होगा, और इंटरप्ट्स के लिए मतदान करने का समय होने पर इसे अनवरोधित करना होगा। यह कुछ यूनिक्स स्वादों की एक विशेषता है लेकिन सभी नहीं, इसलिए पाइथन does not support it (तीसरा "सामान्य नियम" देखें)

  3. ओपी इसे कक्षा के अंदर करना चाहता है। लेकिन इंटरैक्ट फ़ंक्शन सिग्नल हैंडलिंग सिस्टम द्वारा दो तर्कों के साथ आक्रमण किया जाता है: सिग्नल नंबर और स्टैक फ्रेम के लिए पॉइंटर - self तर्क के लिए कोई स्थान क्लास ऑब्जेक्ट तक पहुंच प्रदान नहीं करता है। इसलिए ध्वज सेट करने का सबसे आसान तरीका वैश्विक चर का उपयोग करना है। आप बंद करने का उपयोग करके स्थानीय संदर्भ में एक सूचक को रिग कर सकते हैं (यानी, __init__() में गतिशील रूप से सिग्नल हैंडलर को परिभाषित करें, लेकिन स्पष्ट रूप से मैं परेशान नहीं होगा जब तक कि बहु-थ्रेडिंग या जो भी हो, के कारण कोई वैश्विक प्रश्न न हो।

चेतावनी: यदि आपके प्रक्रिया एक प्रणाली कॉल के बीच में है, एक संकेत हैंडलिंग प्रणाली कॉल बीच में हो सकता है। तो यह सभी अनुप्रयोगों के लिए सुरक्षित नहीं हो सकता है। सुरक्षित विकल्प होंगे (ए) संकेतों पर भरोसा करने के बजाय, प्रत्येक लूप पुनरावृत्ति के अंत में एक गैर-अवरुद्ध पढ़ने का उपयोग करें (और^सी को मारने के बजाय इनपुट टाइप करें; (बी) सिग्नल हैंडलिंग से कार्यकर्ता को अलग करने के लिए धागे या इंटरप्रोसेस संचार का उपयोग करें; या (सी) यदि आप ओएस पर हैं तो असली signal blocking लागू करने का काम करें। उनमें से सभी कुछ हद तक ओएस-निर्भर हैं, इसलिए मैं इसे छोड़ दूंगा।

+0

ठीक है मुझे लगता है कि मैं समझता हूं, लेकिन मेरा काम कक्षा में चल रहा है, तो क्या मुझे सिग्नल_हैंडर को कक्षा के एक समारोह के रूप में परिभाषित करने की आवश्यकता है? – davegri

+0

सिग्नल हैंडलर को नियंत्रण के सामान्य प्रवाह के बाहर बुलाया जाता है। आप इसे क्लास विधि बनाने के लिए _need_ नहीं करते हैं, और मुझे यकीन नहीं है कि यह भी काम करेगा या नहीं। [सिग्नल] (https://docs.python.org/3/library/signal.html) दस्तावेज़ में देख रहे हैं ... – alexis

+0

संक्षिप्त उत्तर: बस एक शीर्ष-स्तरीय फ़ंक्शन और वैश्विक चर का उपयोग करें। जब तक आप बहु-थ्रेडेड नहीं होते हैं, इस मामले में जीवन मुश्किल हो जाता है ... – alexis

9

अनदेखी चलती है जब मैं कार्यक्रम ग सीटीआर + दबाएँ नीचे दिए गए तर्क आप यह कर मदद मिलेगी,

import signal 
import sys 
import time 

run = True 

def signal_handler(signal, frame): 
    global run 
    print "exiting" 
    run = False 

signal.signal(signal.SIGINT, signal_handler) 
while run: 
    print "hi" 
    time.sleep(1) 
    # do anything 
    print "bye" 

जबकि इस चल रहा है, दबाने CTRL + C

0
कोशिश

मुझे आशा है कि आप नीचे दिए गए कोड में मदद मिलेगी:

#!/bin/python 

import sys 
import time 
import signal 

def cb_sigint_handler(signum, stack): 
    global is_interrupted 
    print "SIGINT received" 
    is_interrupted = True 

if __name__ == "__main__": 
    is_interrupted = False 
    signal.signal(signal.SIGINT, cb_sigint_handler) 
    while(1): 
     # do stuff here 
     print "processing..." 
     time.sleep(3) 
     if is_interrupted: 
      print "Exiting.." 
      # do clean up 
      sys.exit(0) 
0

@ praba230890 के समाधान को स्पष्ट करने के लिए: interrupted चर को सही दायरे में परिभाषित नहीं किया गया था। इसे crawl फ़ंक्शन में परिभाषित किया गया था और कार्यक्रम की जड़ पर हैंडलर की परिभाषा के अनुसार हैंडलर वैश्विक चर के रूप में नहीं पहुंच सका।

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