2013-10-26 14 views
5

मेरे पास एक साधारण बोतल स्क्रिप्ट है जो वेब पेज पर बटन प्रक्रियाओं को आगे बढ़ाती है। उसी स्क्रिप्ट के भीतर मैं एक सतत लूप ढूंढ रहा था कि इन बटन प्रेस के लिए अन्य कार्यों के बीच सुनाई गई। मैंने बोतल स्क्रिप्ट को एक अलग थ्रेड में चलाने का प्रयास किया लेकिन यह मेरी अपेक्षा के अनुसार काम नहीं करता है।एक बोतल ऐप थ्रेडिंग

क्या ऐसा करने के लिए कोई बेहतर (या मुझे सही कहना चाहिए) तरीका है?

from bottle import get, post, request, run, redirect 
import threading 

@get('/button') 
def button(): 
    return ''' 
     <form action="/button" method="post"> 
      <input type="submit" value="Push" /> 
     </form> 
    ''' 

@post('/button') 
def action(): 
    print "button pushed" 
    pushed = True 
    redirect("/button") 

#run(host='localhost', port=8080) 
threading.Thread(target=run, kwargs=dict(host='localhost', port=8080)).start() 


def method(): 
    pushed = False 
    print "started" 
    while 1: 
     # do other stuff 
     if pushed: 
      print "push recieved" 
      pushed = False 

method() 

उत्तर

11

क्योंकि यह केवल स्थानीय चर pushedmethod के अंदर परिभाषित के रूप में एक विश्व स्तर पर दिखाई और परिवर्तनीय pushed चर करने का विरोध देखकर है यह काम नहीं करता।

क्या आप के बजाय जरूरत है निम्नलिखित (लेकिन एक सही समाधान के लिए नीचे स्क्रॉल करें):

pushed = False 

@post('/button') 
def action(): 
    global pushed # needed because otherwise assigning to `pushed` will 
        # just create a local variable shadowing the global one 
    pushed = True 
    redirect("/button") 

def method(): 
    # pushed = False <----- this line is not needed, and if enabled, will, again, 
    #       create a local variable shadowing the global one 
    global pushed # again, otherwise the `pushed = False` statement will create a local variable 
    while True: # use real booleans, i.e. True/False not 1/0 
     if pushed: 
      print "push recieved" 
      pushed = False 

method() 

नोट: वेतन टिप्पणियां मैं टुकड़ा के अंदर जोड़ा की ओर ध्यान।

लेकिन वैश्विक चर (या सामान्य चर) के माध्यम से धागे के साथ संवाद करने के लिए यह बुरा अभ्यास है क्योंकि कई अन्य थ्रेड एक ही चर को एक साथ (पढ़ने या लिखने) का उपयोग कर सकते हैं। इसके बजाय, धागे, उपयोग कतारों के बीच की घटनाओं का संकेत देने के:

from Queue import Queue, Empty 

button_pressed = Queue() 

@post('/button') 
def action(): 
    button_pressed.put(1) # can be any value really 
    redirect("/button") 

def method(): 
    while True: 
     try: 
      button_pressed.get_nowait() 
     except Empty: 
      # NOTE: if you don't do anything here, this thread 
      # will consume a single CPU core 
      pass 
     else: 
      print "push recieved" 

get_nowait() जांच करता है कि कुछ कतार में और अगर हां, यह रिटर्न put किया गया है; अन्यथा यह तुरंत Empty उठाता है। आप इसे गैर-शून्य टाइमआउट भी पास कर सकते हैं, या बिना किसी टाइमआउट के कॉल कर सकते हैं, इस स्थिति में यह कतार में कुछ उपलब्ध होने तक प्रतीक्षा करेगा।

थ्रेड को सीपीयू का उपभोग करने के लिए नाइट संस्करण के बजाए टाइमआउट के साथ .get() का उपयोग करना बेहतर है।

इसके अलावा, कोड ऐसी रेखा है जहाँ आप के रूप में जहाँ आप फोन method() मॉड्यूल शीर्ष-स्तरीय दायरे में सीधे नहीं रखा जाना चाहिए और साथ ही धागा शुरू के रूप में;

इस तरह से है कि कोड केवल निष्पादित करेंगे अगर .py फ़ाइल सीधे और नहीं निष्पादित किया जाता है, जब यह एक मॉड्यूल के रूप में आयात किया है: के बजाय, उन्हें सशर्त इस तरह कहते हैं। इसके अलावा, run() को सामान्य रूप से कॉल करने पर विचार करें और इसके बजाय method को थ्रेड के अंदर डालें।

+0

धन्यवाद; थोड़ी देर के बाद से मैंने पाइथन का उपयोग किया, मैं वैश्विक कीवर्ड के बारे में भूल गया। और कतार मॉड्यूल पर अच्छा उदाहरण - मैं पहले कभी ताले इस्तेमाल करता था। – user2921789

+0

@ user2921789: ताले अधिक जटिल हैं और स्केल नहीं करते हैं- इंटर-थ्रेड संचार के लिए कतारों का उपयोग करना लगभग हमेशा बेहतर होता है। यदि आप उसमें रुचि रखते हैं, तो Google "अभिनेता मॉडल" के लिए। –

+0

बस कतार मॉड्यूल एपीआई पढ़ें; सहमत, बिल्कुल वही जो मुझे चाहिए/चाहता था। विशेष रूप से वैकल्पिक 'get()' के साथ जो विपरीत कार्यक्षमता के लिए स्वचालित रूप से ब्लॉक करता है। धन्यवाद। – user2921789