2016-08-02 7 views
6

मैं अपने अजगर मुड़ क्लेन वेब सेवा में दो कार्य है:ट्विस्ट क्लेन में असीमित रूप से कोड निष्पादित करने के लिए कैसे?

@inlineCallbacks 
def logging(data): 
    ofile = open("file", "w") 
    ofile.write(data) 
    yield os.system("command to upload the written file") 

@APP.route('/dostuff') 
@inlineCallbacks 
def dostuff(): 
    yield logging(data) 
    print "check!" 
    returnValue("42") 

os.system("command to upload the written file") रन, यह कह रही है "अपलोड करना शुरू" फिर "पूरा अपलोड" संदेश दिखाई देंगे। मैं लॉगिंग फ़ंक्शन को अतुल्यकालिक बनाना चाहता हूं ताकि logging हैंडलर में प्रसंस्करण dostuff हैंडलर प्रिंट "चेक!" के बाद होता है। (मैं वास्तव में रिटर्न वैल्यू ("42") के बाद होने वाली प्रसंस्करण करना चाहता हूं, लेकिन वे दोनों लॉगिंग फ़ंक्शन एसिंक बना रहे हैं, मुझे लगता है?)

मैंने सोचा कि उपज स्टेटमेंट इसे गैर-अवरुद्ध कर देगा लेकिन ऐसा नहीं लगता है , जाँच!" हमेशा "अपलोड करना शुरू करें" और "अपलोड पूर्ण" के बाद मुद्रित हो जाता है। अगर मैं एसिंक कोडिंग के लिए नया हूं और थोड़ी देर के लिए इस पर अवरुद्ध हो गया हूं तो मैं इस पर कुछ फीडबैक दे सकता हूं ...

उत्तर

3

अपना कोड एसिंक बनाने के लिए आपको Twisted Deferredsdescribed here के रूप में उपयोग करने की आवश्यकता है। डिफर्ड आपको एसिंक्रोनस कोड निष्पादन के लिए एक एपीआई देते हैं, वे आपको अपने कार्यों में कॉलबैक संलग्न करने की अनुमति देते हैं और वे रिएक्टर ऑब्जेक्ट द्वारा प्रबंधित ट्विस्टेड इवेंट लूप में कोड निष्पादित करते हैं।

मुझे आपके मामले में डिफर्रेड का उपयोग करने के दो संभावित तरीके दिखाई देते हैं।

1) reactor.callLater()

साथ पृष्ठभूमि में कार्य निष्पादित यह ठीक है अगर dostuff हैंडलर परिणाम के बारे में परवाह नहीं है। आप reactor.callLater() का उपयोग कर सकते हैं। doStuff से मूल्य वापस करने के बाद इस तरह आपका async फ़ंक्शन निष्पादित होगा।

तो कुछ इस तरह:

from klein import run, route, Klein 
from twisted.internet import defer, task, reactor 
import os 

app = Klein() 


def logging(data): 
    ofile = open("file", "w") 
    ofile.write(data) 
    result = os.system("ls") 
    print(result) 


@route('/') 
def dostuff(request): 
    reactor.callLater(0, logging, "some data") 
    print("check!") 
    return b'Hello, world!' 

run("localhost", 8080) 

इस कोड के साथ ईवेंट के क्रम में पीछा कर रहा है, पहले "जाँच" छपा है, फिर "हैलो दुनिया" प्रतिसाद दिया और अंत async कॉल suceeds और प्रिंट में है os.system() चलाने के परिणाम।

2016-08-11 08:52:33+0200 [-] check! 
2016-08-11 08:52:33+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:52:32 +0000] "GET/HTTP/1.1" 200 13 "-" "curl/7.35.0" 
a.py file 

2) पृष्ठभूमि में कार्य निष्पादित और task.deferLater()

साथ परिणाम प्राप्त आप अपने 'प्रवेश' समारोह के परिणाम आप भी इस वस्तु को कॉलबैक देते हैं और twisted.internet.task एपीआई का उपयोग कर सकते हैं के बारे में परवाह है। आप इस

@route('/') 
def dostuff(request): 
    def the_end(result): 
     print("executed at the end with result: {}".format(result)) 
    dfd = task.deferLater(reactor, 0, logging, "some data") 
    dfd.addCallback(the_end) 
    print("check!") 
    return b'Hello, world!' 

की तरह काम करने के लिए इस तरह से आप अपने हैंडलर refactor करने के लिए की जरूरत जाना चाहते हैं घटनाओं के इस तरह से क्रम से ऊपर के रूप में ही होगा, लेकिन अपने logging समारोह खत्म होने के बाद the_end समारोह अंत में क्रियान्वित की जाएगी।

2016-08-11 08:59:24+0200 [-] check! 
2016-08-11 08:59:24+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:59:23 +0000] "GET/HTTP/1.1" 200 13 "-" "curl/7.35.0" 
a.py file 
2016-08-11 08:59:24+0200 [-] executed at the end with result: some result 
+0

चूंकि ट्विस्ट क्लेन के लिए मेरा ज्ञान ज्यादातर http://tavendo.com/blog/post/going-asynchronous-from-flask-to-twisted-klein/ से आपकी प्रतिक्रिया से आ रहा है, आपकी प्रतिक्रिया मुझे बहुत मददगार है। मैंने अभी तक कोशिश नहीं की लेकिन मुझे लगता है कि यह सही है। आपका बहुत बहुत धन्यवाद। वास्तव में इसकी सराहना की। – JLTChiu

+0

एक अद्यतन के रूप में, कोड काम करता है, लेकिन मेरा पाइचर्म और पिलिंट 'ई: 512, 4: मॉड्यूल' twisted.internet.reactor 'पर त्रुटियों को दिखा रहा है' कोई 'कॉललेटर' सदस्य नहीं है (कोई सदस्य नहीं है) लेकिन समस्या यह कोड है पूरी तरह से ठीक लगता है (यह इरादे के रूप में काम करता है)। क्या इसे ठीक करने का कोई तरीका है? – JLTChiu

+1

पिचर्म कोड निरीक्षण में कुछ बग की तरह दिखता है, कुछ प्लेटफार्म विशिष्ट हो सकता है? आपको यह जांचना होगा कि इस तरह की जांच करते समय क्या पिचर्म दिखता है और यह कोड के इस विशिष्ट टुकड़े में क्यों विफल रहता है। मैं खुद को पिचर्म का उपयोग करता हूं और मैं वास्तव में इसकी स्टाइल चेतावनियों पर भरोसा नहीं करता हूं, उनमें से कई झूठे अलार्म हैं। flake8 पायथन कोड शैली की जांच के लिए बेहतर उपकरण है IMO –

1

'उपज' कथन चीजों को असंकालिक रूप से नहीं करता है। यह केवल उस फ़ंक्शन के निष्पादन को रोकता है और एक जेनरेटर ऑब्जेक्ट देता है जिसे बाद में अनुक्रम को फिर से चलाने के लिए उपयोग किया जा सकता है।

तो dostuff() जनरेटर ऑब्जेक्ट को वापस करने जा रहा है। तब तक कुछ भी नहीं होगा जब तक कि जेनरेटर ऑब्जेक्ट को बाद में दोहराया न जाए। लेकिन ऐसा करने के लिए आपके कोड में कुछ भी नहीं है। मुझे उम्मीद है कि आपकी डोस्टफ रूटीन एक वाक्यविन्यास त्रुटि उत्पन्न करेगी क्योंकि इसमें उपज और एक खाली रिक्त दोनों शामिल हैं। लॉगिंग दिनचर्या कुछ भी नहीं करेगी क्योंकि इसमें उपज होती है और जेनरेटर जो रिटर्न देता है उसका कभी भी उपयोग नहीं किया जाता है।

अंत में, लॉगिंग दिनचर्या हर बार इसे अपनी आउटपुट फ़ाइल को छोटा करने जा रही है क्योंकि यह प्रत्येक आमंत्रण पर मोड 'डब्ल्यू' के साथ लॉग फ़ाइल खोलता है।

असीमित निष्पादन के लिए, आपको मल्टीप्रोसेसिंग के कुछ रूपों की आवश्यकता है। लेकिन मुझे नहीं लगता कि इस संदर्भ में इसकी आवश्यकता है। आपका लॉगिंग फ़ंक्शन काफी हल्का वजन है और जल्दी से चलना चाहिए और डोस्टफ के काम में हस्तक्षेप नहीं करना चाहिए।

मैं कुछ इस तरह की कोशिश कर रहा सुझाव है:

@inlineCallbacks 
def logging(data): 
    try: 
     logging._ofile.write(data + '\n') 
    except AttributeError: 
     logging._ofile = open("file", 'w') 
     logging._ofile.write(data + '\n') 

@APP.route('/dostuff') 
@inlineCallbacks 
def dostuff(): 
    logging("before!") 
    os.system("command to upload the written file") 
    logging("after!") 
    return("42") 

यहाँ हम केवल एक बार प्रवेश फ़ाइल खोलते हैं, जब _ofile लॉगिंग की एक विशेषता के रूप में परिभाषित नहीं किया गया है पहली बार प्रवेश कहा जाता है। बाद की कॉल पर, logging._ofile पहले से ही खुलेगा और कोशिश ब्लॉक में लेखन कथन सफल होगा।

रूटीन डोस्टफ() कॉलिंग लॉग इन करने के लिए लॉग इन करता है कि हम काम करने वाले हैं, वास्तव में काम करते हैं, फिर काम करने के संकेत देने के लिए लॉगिंग कहते हैं, और आखिरकार वांछित मूल्य देता है।

+0

dostuff अपने कोड नमूने में async नहीं है, यह 'os.system' फोन पर अवरुद्ध कर देगा, तो" अपलोड करना शुरू "और 'पूरा अपलोड' –

+0

सच dostuff से लौटने से पहले प्रिंट किया जाएगा। अपने ट्विस्ट ज्ञान के साथ चिमटा करने के लिए धन्यवाद। –

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