2009-12-09 11 views
8

पर डेटा उपलब्ध होने पर परिणाम वेबपृष्ठ पर परिणाम प्रदर्शित करें मैं पाइथन में एक सीजीआई पृष्ठ लिख रहा हूं। मान लें कि एक ग्राहक मेरे सीजीआई पेज पर अनुरोध भेजता है। मेरा सीजीआई पृष्ठ गणना करता है और जैसे ही यह पहला आउटपुट होता है, यह उस आउटपुट को क्लाइंट को वापस भेजता है, लेकिन यह गणना करने के लिए जारी करेगा और अन्य प्रतिक्रियाएं के बाद पहली प्रतिक्रिया भेजी जाती है।सर्वर पर

क्या मैंने यहां प्रस्तुत किया है? मैं इस सवाल से पूछता हूं क्योंकि मेरे सीमित ज्ञान में, सीजीआई पेज प्रतिक्रियाओं में एक बार मूलभूत भेजा जाता है, प्रतिक्रिया मिलने के बाद, सीजीआई-पेज चलना बंद हो जाता है। यह बात सर्वर साइड या क्लाइंट साइड पर बनाई गई है, और मैं इसे कैसे कार्यान्वित कर सकता हूं?

मेरा सर्वर अपाचे चला रहा है। आपका बहुत बहुत धन्यवाद।

मैंने इस मंच में "डीआरआर" से क्लाइंट कोड का प्रयास किया है (धन्यवाद, मुझे यह पता चला कि कितना समय-समय पर मतदान कार्य करता है)।

import sys 
if __name__ == "__main__": 
    sys.stdout.write("Content-Type: text/html\r\n\r\n") 
    print "<html><body>" 
    for i in range(10): 
     print "<div>%s</div>" % i 
     sys.stdout.flush() 
    print "</body></html>" 

मैं एक समय में 1 संख्या प्रदर्शित करने के लिए मेरे मुवक्किल पेज की उम्मीद कर रहा हूँ (0,1,2, ...), लेकिन हमेशा डेटा:

<html> 
<head> 
    <title>BargePoller</title> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script> 

    <style type="text/css" media="screen"> 
     body{ background:#000;color:#fff;font-size:.9em; } 
     .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid} 
     .old{ background-color:#246499;} 
     .new{ background-color:#3B9957;} 
    .error{ background-color:#992E36;} 
    </style> 

    <script type="text/javascript" charset="utf-8"> 
    function addmsg(type, msg){ 
     /* Simple helper to add a div. 
     type is the name of a CSS class (old/new/error). 
     msg is the contents of the div */ 
     $("#messages").append(
      "<div class='msg "+ type +"'>"+ msg +"</div>" 
     ); 
    } 

    function waitForMsg(){ 
     /* This requests the url "msgsrv.php" 
     When it complete (or errors)*/ 
     $.ajax({ 
      type: "GET", 
      url: "msgsrv.php", 

      async: true, /* If set to non-async, browser shows page as "Loading.."*/ 
      cache: false, 
      timeout:50000, /* Timeout in ms */ 

      success: function(data){ /* called when request to barge.php completes */ 
       addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/ 
       setTimeout(
        'waitForMsg()', /* Request next message */ 
        1000 /* ..after 1 seconds */ 
       ); 
      }, 
      error: function(XMLHttpRequest, textStatus, errorThrown){ 
       addmsg("error", textStatus + " (" + errorThrown + ")"); 
       setTimeout(
        'waitForMsg()', /* Try again after.. */ 
        "15000"); /* milliseconds (15seconds) */ 
      }, 
     }); 
    }; 

    $(document).ready(function(){ 
     waitForMsg(); /* Start the inital request */ 
    }); 
    </script> 
</head> 
<body> 
    <div id="messages"> 
     <div class="msg old"> 
      BargePoll message requester! 
     </div> 
    </div> 
</body> 
</html> 

और यहाँ अपने सर्वर कोड है एक बार में बाहर आता है (...)। कृपया इसे समझने में मेरी सहायता करें। धन्यवाद आप लोग बहुत ज्यादा।

बस थोड़ा सा ट्रैक, मैं jquery धूमकेतु प्लगइन का उपयोग करने की कोशिश कर रहा हूं, लेकिन मुझे पर्याप्त दस्तावेज नहीं मिला। मदद की बहुत सराहना की जाएगी। धन्यवाद फिर से: डी

[संपादित करें] ठीक है दोस्तों, आखिरकार आपके गाइड के लिए धन्यवाद, मैंने इसे काम करने में कामयाब रहा है। जब आप भविष्यवाणी करते हैं कि mod_deflate यह सब का स्रोत है, तो आप सही कह रहे हैं।

सारांश में, मैं यहाँ क्या किया है:

  • ग्राहक के लिए, ऊपर

  • सर्वर के लिए HTML कोड के रूप में एक लंबे सर्वेक्षण पेज बनाने के लिए, द्वारा mod_deflate निष्क्रिय कर दें: संपादन फ़ाइल/आदि/apache2/mods-available/deflate.conf, टेक्स्ट/एचटीएमएल भाग के साथ लाइन को टिप्पणी करें और सर्वर को पुनरारंभ करें। यह सुनिश्चित करने के लिए कि पाइथन आउटपुट को स्वयं बफर नहीं करता है, पृष्ठ की शुरुआत में #!/Usr/bin/python -u शामिल करें। प्रत्येक प्रिंटिंग के बाद sys.stdout.flush() का उपयोग करना याद रखें जिसे आप क्लाइंट में दिखाना चाहते हैं। प्रभाव पारदर्शी नहीं हो सकता है, परीक्षण करने के लिए time.sleep (1) शामिल होना चाहिए। : डी का समर्थन करने और इस को हल करने में मदद के लिए बहुत बहुत

धन्यवाद तुम लोग: डी

उत्तर

8

के साथ किया जाता है।

पारंपरिक सर्वर-आधारित दृष्टिकोण के जहां स्क्रिप्ट सिर्फ एक बार चलाता है, लेकिन पूरा करने के लिए एक लंबा समय लगता, पेज के टुकड़े बाहर थूकना के रूप में यह जाता है:

import sys, time 

sys.stdout.write('Content-Type: text/html;charset=utf-8\r\n\r\n') 

print '<html><body>' 
for i in range(10): 
    print '<div>%i</div>'%i 
    sys.stdout.flush() 
    time.sleep(1) 

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

WSGI-ओवर-सीजीआई उदाहरण:

import time, wsgiref.handlers 

class MyApplication(object): 
    def __call__(self, environ, start_response): 
     start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')]) 
     return self.page() 

    def page(self): 
     yield '<html><body>' 
     for i in range(10): 
      yield '<div>%i</div>'%i 
      time.sleep(1) 

application= MyApplication() 
if __name__=='__main__': 
    wsgiref.handlers.CGIHandler().run(application) 

ध्यान रखें कि आपके वेब सर्वर का अपना बफरिंग जोड़कर इस दृष्टिकोण (सीजीआई या WSGI के लिए) को विफल कर सकते हैं। यह आमतौर पर तब होता है जब आप आउटपुट-ट्रांसफॉर्मिंग फ़िल्टर का उपयोग कर रहे हैं जैसे mod_deflate स्वचालित रूप से वेबएप आउटपुट को संपीड़ित करने के लिए। आपको आंशिक-प्रतिक्रिया-उत्पन्न स्क्रिप्ट के लिए संपीड़न बंद करना होगा।

यह पृष्ठ को बिट-बाय-बिट प्रस्तुत करने के लिए आपको सीमित करता है क्योंकि नया डेटा आता है।आप नए डेटा में आता है के रूप में क्लाइंट साइड पेज फेरबदल की देखभाल कर रहा है, जैसे .:

def page(self): 
    yield (
     '<html><body><div id="counter">-</div>' 
     '<script type="text/javascript">' 
     ' function update(n) {' 
     '  document.getElementById("counter").firstChild.data= n;' 
     ' }' 
     '</script>' 
    ) 
    for i in range(10): 
     yield '<script type="text/javascript">update(%i);</script>'%i 
     time.sleep(1) 

यह क्लाइंट-साइड स्क्रिप्टिंग पर निर्भर करता है के द्वारा यह खूबसूरत बना सकते हैं तो यह एक अच्छा विचार है बैकअप शामिल करने के लिए हो सकता है अंत में गैर-स्क्रिप्ट-आधारित अंतिम आउटपुट।

यह सब करते समय, पृष्ठ अभी भी लोड हो रहा प्रतीत होता है। यदि आप इसे नहीं चाहते हैं, तो आपको स्क्रिप्ट को पहले अनुरोध में विभाजित करने की आवश्यकता होगी जो केवल क्लाइंट-साइड स्क्रिप्ट समेत स्थिर सामग्री को थूकता है जो सर्वर के साथ वापस एक XMLHttpRequest का उपयोग करके जांचता है कि यह नए डेटा के लिए मतदान करता है वास्तव में लंबे समय से चलने वाले मामलों के लिए, या कई XMLHttpRequests जिनमें से प्रत्येक स्थिति और कोई नया डेटा देता है। यह दृष्टिकोण अधिक जटिल है क्योंकि इसका मतलब है कि आपको वेब सर्वर के अलावा पृष्ठभूमि कार्य प्रक्रिया के रूप में अपनी कार्य प्रक्रिया को चलाने की ज़रूरत है, और उदाहरण के लिए डेमन और फ्रंट-एंड CGI/WSGI अनुरोध के बीच डेटा पास करना है। पाइप या डेटाबेस।

+0

प्रभावशाली विस्तृत उत्तर। आपके लिए बहुत अच्छा काम धन्यवाद: डी। मे लूँगा जितनी जल्दी हो सके इसे आजमाएं। – wakandan

+0

मैंने jquery-समर्थित के साथ एक साधारण पृष्ठ का उपयोग करके इसका परीक्षण किया है। ऐसा प्रतीत होता है कि सभी परिणाम आते हैं और एक क्रमशः नहीं। मैं यहाँ क्या खो रहा हूँ? – wakandan

+0

शायद आपके पास सर्वर पर अतिरिक्त बफरिंग करने वाला एक फ़िल्टर है। जिसने इसे काम करना बंद कर दिया था वह ऊपर उल्लेखित mod_deflate था, लेकिन अन्य फ़िल्टरों का भी असर हो सकता है। – bobince

1

हाँ thats संभव है और आप की जरूरत नहीं है बहुत, के रूप में आप डेटा का प्रिंट आउट, सर्वर भेज देंगे है, बस सुनिश्चित करने के लिए stdout

+0

उत्तर के लिए धन्यवाद। लेकिन मुझे यकीन नहीं है कि यह इस तरह से संभव है। यदि आप केवल डेटा प्रिंट करते हैं, तो प्रतिक्रिया केवल स्क्रिप्ट पूरा होने के बाद भेजी जा सकती है, है ना? – wakandan

+0

जैसा कि अन्य उत्तरों ने विवरण में समझाया है, आपको केवल हमारे प्रिंट करना होगा और फ्लश करना होगा क्योंकि मैंने –

+0

का उल्लेख किया है जैसा कि आपने यहां बताया है, मैं स्टडआउट को फ्लश कर रहा हूं, लेकिन यह क्लाइंट पेज पर आता है, यह डेटा का एक बड़ा हिस्सा प्रदर्शित करता रहता है यकायक। नहीं समझ सके। :( – wakandan

1

कुछ तकनीकें हैं।

पुराने तरीके से डेटा स्ट्रीम करना जारी रखना है, और ब्राउज़र को प्रगतिशील प्रतिपादन का उपयोग करके इसे प्रस्तुत करना जारी रखना है। तो एक पुराने फैशन सीजीआई के रूप में, बस sys.stdout.flush() करें। यह एक आंशिक पृष्ठ दिखाता है जिसे आप जोड़ना जारी रख सकते हैं, लेकिन यह ब्राउज़र में बेकार दिखता है क्योंकि थ्रोबबर कताई रखेगा और ऐसा लगता है कि सर्वर लटका हुआ है या अधिभारित है।

कुछ ब्राउज़र एक विशेष मल्टीपार्ट mimetype multipart/x-mixed-replace का समर्थन करते हैं जो आपको कनेक्शन को खोलने की एक ही चाल करने की अनुमति देता है, लेकिन जब आप अगले मल्टीपार्ट खंड (जो एमआईएम-फॉर्मेटेड होना चाहिए) भेजते हैं तो ब्राउज़र पूरी तरह से पृष्ठ को प्रतिस्थापित करेगा। मुझे नहीं पता कि यह प्रयोग योग्य है - इंटरनेट एक्सप्लोरर इसका समर्थन नहीं करता है और यह अन्य ब्राउज़र में भी अच्छा काम नहीं कर सकता है।

अगला सबसे आधुनिक तरीका जावास्क्रिप्ट के XMLHttpRequest के साथ परिणामों के लिए सर्वर को मतदान कर रहा है। इसके लिए आप एक अलग वेबसर्वर थ्रेड या प्रक्रिया से ऑपरेशन के परिणामों की जांच कर सकते हैं, जो सर्वर-साइड कोड में प्राप्त करने के लिए काफी कठिन हो सकता है। यह आपको यद्यपि एक बहुत अच्छा वेब पेज बनाने की अनुमति देता है।

यदि आप और भी जटिल होना चाहते हैं, तो "धूमकेतु" मॉडल या "वेब सॉकेट" देखें।

+0

उत्तर के लिए धन्यवाद। मुझे यकीन नहीं है कि मैं इसे समझ सकता हूं: डी। मुझे बहुत सराहना की जाएगी यदि आप मुझे कुछ उदाहरण दे सकते हैं, खासकर sys.stdout.flush() का उपयोग करके पहला भाग ... – wakandan

+0

मैंने sys.stdout.flush() फ़ंक्शन का उपयोग करके कहा है, लेकिन किसी भी तरह से सभी डेटा परिणाम एक पर हैं और मुझे यह नहीं मिल रहा है। क्या मुझे यहां कुछ याद आ रहा है? – wakandan

1

पुराने जमाने CGI कार्यक्रमों में चाल Transfer-Encoding: chunked HTTP हेडर उपयोग कर रहा है:

3.6.1 chunked स्थानांतरण कोडिंग

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

परिणाम उपलब्ध होने पर, इसे एक अलग खंड के रूप में भेजें - ब्राउज़र इस स्वयं निहित HTTP संदेश को प्रदर्शित करेगा। जब एक और खंड बाद में आता है, तो नया पृष्ठ प्रदर्शित होता है।

आपको CGI प्रोग्राम के अंदर प्रत्येक खंड के लिए सही शीर्षलेख तैयार करना होगा। साथ ही, प्रत्येक खंड के अंत में CGI आउटपुट को फ़्लश करना याद रखें। पायथन में यह sys.stdout.flush()

+0

चंक किए गए स्थानांतरण-कोडिंग दृश्यों के पीछे क्या चल रहा है, लेकिन आपको हेडर खुद को उत्पन्न करने की ज़रूरत नहीं है, वेब सर्वर आपके लिए यह करेगा। – bobince

+0

मैंने इस चाल को आजमाया लेकिन दुख की बात यह काम नहीं करती है। – wakandan

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