PyQt एप्लिकेशन में थ्रेडिंग: Qt थ्रेड्स या पायथन थ्रेड्स का उपयोग करें?


116

मैं एक GUI एप्लिकेशन लिख रहा हूं जो नियमित रूप से एक वेब कनेक्शन के माध्यम से डेटा पुनर्प्राप्त करता है। चूँकि यह पुनर्प्राप्ति में कुछ समय लगता है, इससे UI पुनः प्राप्ति प्रक्रिया के दौरान अनुत्तरदायी हो जाता है (इसे छोटे भागों में विभाजित नहीं किया जा सकता है)। यही कारण है कि मैं एक अलग वर्कर थ्रेड के लिए वेब कनेक्शन को आउटसोर्स करना चाहता हूं।

[हाँ, मुझे पता है, अब मुझे दो समस्याएं हैं ।]

वैसे भी, एप्लिकेशन PyQt4 का उपयोग करता है, इसलिए मैं जानना चाहता हूं कि बेहतर विकल्प क्या है: Qt के थ्रेड्स का उपयोग करें या पायथन threadingमॉड्यूल का उपयोग करें ? प्रत्येक के फायदे / नुकसान क्या हैं? या आपके पास एक पूरी तरह से अलग सुझाव है?

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

देशी पायथन थ्रेड्स ( threadingमॉड्यूल से) पर PyQt4's (यानी Qt) थ्रेड्स का उपयोग करने के क्या फायदे और नुकसान हैं ?


संपादन 2: आप सभी के उत्तर के लिए धन्यवाद। यद्यपि कोई 100% समझौता नहीं है, लेकिन व्यापक सहमति प्रतीत होती है कि इसका उत्तर "क्यूटी का उपयोग करें" है, क्योंकि इसका लाभ बाकी लाइब्रेरी के साथ एकीकरण है, जबकि कोई वास्तविक नुकसान नहीं है।

किसी के लिए दो सूत्रण कार्यान्वयन के बीच चयन करने की तलाश में, मैं अत्यधिक सलाह देता हूं कि वे यहां दिए गए सभी उत्तरों को पढ़ें, जिसमें पायट मेलिंग सूची थ्रेड शामिल है जो एबॉट से लिंक करता है।

बाउंटी के लिए मेरे विचार में कई उत्तर थे; अंत में मैंने बहुत प्रासंगिक बाहरी संदर्भ के लिए मठाधीश को चुना; हालांकि, यह एक करीबी कॉल था।

एक बार फिर धन्यवाद।

जवाबों:


106

PyQt मेलिंग सूची में बहुत समय पहले इस पर चर्चा नहीं की गई थी। इस विषय पर जियोवानी बाजो की टिप्पणियों का उद्धरण :

यह ज्यादातर एक ही है। मुख्य अंतर यह है कि क्यूटीह्रेड्स क्यूटी (एसिंक्रोनस सिग्नल / स्लॉट्स, इवेंट लूप, आदि) के साथ बेहतर एकीकृत हैं। इसके अलावा, आप एक पायथन थ्रेड से Qt का उपयोग नहीं कर सकते हैं (आप उदाहरण के लिए घटना को QApplication.postEvent के माध्यम से मुख्य थ्रेड के लिए नहीं कर सकते हैं): इसके लिए आपको एक काम करने की आवश्यकता है।

अंगूठे का एक सामान्य नियम हो सकता है कि आप क्यूएचटी का उपयोग करें यदि आप किसी तरह क्यूटी के साथ बातचीत करने जा रहे हैं, और पायथन धागे का उपयोग करें अन्यथा।

और कुछ पहले PyQt के लेखक के इस विषय पर टिप्पणी: "वे दोनों एक ही मूल धागा कार्यान्वयन के आसपास रैपर हैं"। और दोनों कार्यान्वयन समान रूप से GIL का उपयोग करते हैं।


2
अच्छा उत्तर, लेकिन मुझे लगता है कि आपको स्पष्ट रूप से यह दिखाने के लिए कि आपको वास्तव में सारांशित नहीं करना है लेकिन मेलिंग सूची से Giovanni Bajo को उद्धृत करते हुए :)
c089

2
मुझे आश्चर्य है कि आप QApplication.postEvent () के माध्यम से मुख्य थ्रेड पर घटनाओं को पोस्ट क्यों नहीं कर सकते हैं और इसके लिए एक qhread की आवश्यकता है? मुझे लगता है कि मैंने लोगों को ऐसा करते देखा है और यह काम किया है।
प्रातः

1
मैंने QCoreApplication.postEventएक आवेदन में 100 गुना प्रति सेकंड की दर से पायथन धागे से कॉल किया है, जो एक क्रॉस-प्लेटफ़ॉर्म चलाता है और 1000 घंटों तक परीक्षण किया गया है। मैंने उससे कभी कोई समस्या नहीं देखी। मुझे लगता है कि यह तब तक ठीक है जब तक कि गंतव्य ऑब्जेक्ट मैनट्रेड या एक क्यूथ्रेड में स्थित है। मैंने इसे एक अच्छी लाइब्रेरी में भी लपेटा, क्यूटिल्स देखें ।
तीन_पिनएप्पल्स

2
इस सवाल और जवाब की अत्यधिक मतदान की प्रकृति को देखते हुए, मुझे लगता है कि यह एक हाल ही में एसओ उत्तर को इंगित करने के लायक है, जो कि उन स्थितियों पर विस्तृत है, जिसमें पायथन थ्रेड्स से कुछ क्यूटी विधियों का उपयोग करना सुरक्षित है। यह देखे गए व्यवहार के साथ लंबा होता है जिसे स्वयं और @Trilarion द्वारा देखा गया है।
तीन_पिनएप्पल्स

33

पायथन के धागे सरल और सुरक्षित होंगे, और चूंकि यह आई / ओ-आधारित अनुप्रयोग के लिए है, इसलिए वे जीआईएल को बायपास करने में सक्षम हैं। उस ने कहा, क्या आपने ट्विस्टेड या नॉन-ब्लॉकिंग सॉकेट / चयन का उपयोग करते हुए गैर-अवरोधक I / O पर विचार किया है?

संपादित करें: थ्रेड्स पर अधिक

पायथन धागे

पायथन के धागे सिस्टम थ्रेड हैं। हालांकि, पायथन यह सुनिश्चित करने के लिए एक वैश्विक दुभाषिया लॉक (GIL) का उपयोग करता है कि दुभाषिया कभी भी एक समय में बाइट-कोड निर्देशों के एक निश्चित आकार ब्लॉक को निष्पादित कर रहा है। सौभाग्य से, पायथन इनपुट / आउटपुट ऑपरेशन के दौरान जीआईएल जारी करता है, जिससे गैर-अवरुद्ध I / O के अनुकरण के लिए धागे उपयोगी हो जाते हैं।

महत्वपूर्ण चेतावनी: बाइट-कोड निर्देशों की संख्या के बाद से यह भ्रामक हो सकता है की संख्या एक कार्यक्रम में लाइनों की संख्या के अनुरूप नहीं है । यहां तक ​​कि पायथन में एक भी असाइनमेंट परमाणु नहीं हो सकता है, इसलिए कोड के किसी भी ब्लॉक के लिए एक म्यूटेक्स लॉक आवश्यक है जिसे जीआईएल के साथ भी परमाणु रूप से निष्पादित किया जाना चाहिए।

क्यूटी धागे

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

क्यूटी धागे जारी किए गए जीआईएल के साथ काम करते हैं। क्यूटी थ्रेड्स क्यूटी लाइब्रेरी कोड (और अन्य संकलित मॉड्यूल कोड जो GIL का अधिग्रहण नहीं करता है) को समवर्ती रूप से निष्पादित करने में सक्षम हैं। हालाँकि, पायथन कोड को क्यूटी थ्रेड के संदर्भ में अभी भी निष्पादित किया गया है जीआईएल को प्राप्त करता है, और अब आपको अपने कोड को लॉक करने के लिए तर्क के दो सेटों का प्रबंधन करना होगा।

अंत में, क्यूटी थ्रेड्स और पायथन थ्रेड्स दोनों सिस्टम थ्रेड्स के आसपास रैपर हैं। पायथन धागे का उपयोग करने के लिए थोड़ा सुरक्षित है, क्योंकि उन हिस्सों को जो पायथन में नहीं लिखे गए हैं (स्पष्ट रूप से जीआईएल का उपयोग कर रहे हैं) किसी भी मामले में जीआईएल का उपयोग करते हैं (हालांकि ऊपर चेतावनी अभी भी लागू होती है।)

गैर-अवरुद्ध I / O

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

एसिंक्रोनस I / O के साथ, आप हमेशा सुनिश्चित कर सकते हैं कि, प्रत्येक खुले वर्णनकर्ता के लिए, निष्पादन का मार्ग सुसंगत और व्यवस्थित है। जाहिर है, ऐसे मुद्दों को संबोधित किया जाना चाहिए, जैसे कि क्या करना है जब एक खुले चैनल के आधार पर कोड आगे कोड के परिणामों पर निर्भर करता है जब किसी अन्य खुले चैनल ने डेटा वापस किया।

इवेंट-आधारित, गैर-अवरुद्ध I / O के लिए एक अच्छा समाधान नया डीजल है पुस्तकालय है। यह फिलहाल लिनक्स पर ही सीमित है, लेकिन यह असाधारण रूप से तेज और काफी सुरुचिपूर्ण है।

यह भी अपने समय जानने के लिए लायक है pyevent , अद्भुत libevent पुस्तकालय है, जो घटना के आधार पर आपके सिस्टम के लिए सबसे तेजी से उपलब्ध विधि (संकलन समय पर निर्धारित) का उपयोग प्रोग्रामिंग के लिए एक बुनियादी रूपरेखा प्रदान करता है के चारों ओर एक आवरण।


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

2
कुछ भी नहीं वास्तव में GIL को बायपास करता है। लेकिन पायथन ने I / O संचालन के दौरान GIL जारी किया। पायथन जीआईएल को भी जारी करता है जब संकलित मॉड्यूल को the हैंड ऑफ ’करता है, जो स्वयं जीआईएल प्राप्त करने / जारी करने के लिए जिम्मेदार होते हैं।
जेफ ओबर

2
अपडेट सिर्फ गलत है। पायथन कोड पायथन थ्रेड में बिल्कुल उसी तरह से चलता है जैसे कि एक क्यूथ्रेड में। जब आप पायथन कोड चलाते हैं, तो आप जीआईएल को प्राप्त करते हैं (और फिर पायथन थ्रेड्स के बीच निष्पादन को प्रबंधित करता है), आप इसे तब जारी करते हैं जब आप C ++ कोड चलाते हैं। कोई अंतर नहीं है।
लुकास लालकिंसी

1
नहीं, मुद्दा यह है कि आप धागा कैसे बनाते हैं, इससे कोई फर्क नहीं पड़ता, पायथन दुभाषिया परवाह नहीं करता है। सभी के बारे में परवाह है कि यह जीआईएल का अधिग्रहण कर सकता है और एक्स निर्देशों के बाद इसे जारी / पुनः प्राप्त कर सकता है। उदाहरण के लिए आप C लाइब्रेरी से कॉलबैक बनाने के लिए ctypes का उपयोग कर सकते हैं, जिसे एक अलग थ्रेड में कहा जाएगा, और कोड एक अलग थ्रेड को जाने बिना भी ठीक काम करेगा। थ्रेड मॉड्यूल के बारे में वास्तव में कुछ खास नहीं है।
लुकास लालकिंशी

1
आप कह रहे थे कि लॉकिंग के बारे में क्यूथ्रेड अलग कैसे है और "आपको अपने कोड को लॉक करने के लिए तर्क के दो सेटों का प्रबंधन कैसे करना है"। मैं जो कह रहा हूं, वह बिल्कुल अलग नहीं है। मैं थ्रेड शुरू करने के लिए ctypes और pthread_create का उपयोग कर सकता हूं, और यह ठीक उसी तरह काम करेगा। पायथन कोड को केवल GIL की परवाह नहीं करनी है।
लुकास लालिन्स्की

21

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

यदि आप एक HTTP सर्वर तक पहुंच रहे हैं, तो आपको विचार करना चाहिए QNetworkAccessManager


1
इसके अलावा मैंने जेफ ओबेर के जवाब पर जो टिप्पणी की, वह QNetworkAccessManagerआशाजनक लग रही है। धन्यवाद।
बाल्फा

13

मैंने खुद से वही सवाल पूछा जब मैं PyTalk के लिए काम कर रहा था

यदि आप Qt का उपयोग कर रहे हैं, तो आपको उपयोग करने की आवश्यकता है QThread Qt ढांचे करने में सक्षम होने के करने की और पूरी तरह से सिग्नल / स्लॉट सिस्टम।

सिग्नल / स्लॉट इंजन के साथ, आप एक थ्रेड से दूसरे और अपने प्रोजेक्ट के हर हिस्से के साथ बात कर पाएंगे।

इसके अलावा, इस पसंद के बारे में बहुत अच्छा सवाल नहीं है क्योंकि दोनों एक C ++ बाइंडिंग हैं।

यहाँ PyQt और थ्रेड का मेरा अनुभव है।

मैं आपको उपयोग करने के लिए प्रोत्साहित करता हूं QThread


9

जेफ के कुछ अच्छे अंक हैं। कोई भी GUI अपडेट केवल एक मुख्य थ्रेड ही कर सकता है। यदि आपको GUI को थ्रेड के भीतर से अपडेट करने की आवश्यकता है, तो Qt-4 के कतारबद्ध कनेक्शन सिग्नल थ्रेड्स में डेटा भेजना आसान बनाते हैं और यदि आप क्यूथ्रेड का उपयोग कर रहे हैं तो स्वचालित रूप से इनवॉइस किया जाएगा; मुझे यकीन नहीं है कि यदि आप पायथन थ्रेड्स का उपयोग कर रहे हैं तो वे होंगे, हालांकि इसके लिए एक पैरामीटर जोड़ना आसान है connect()


5

मैं वास्तव में सिफारिश नहीं कर सकता, लेकिन मैं सीपीथॉन और क्यूटी थ्रेड्स के बीच अंतर का वर्णन करने की कोशिश कर सकता हूं।

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

दूसरी ओर, हमारे पास क्यूटी थ्रेड्स हैं, जो मूल रूप से सिस्टम थ्रेड्स पर सामान्य परत हैं, ग्लोबल इंटरप्रेटर लॉक नहीं है, और इस प्रकार समवर्ती चलाने में सक्षम हैं। मुझे यकीन नहीं है कि PyQt इससे कैसे निपटता है, हालाँकि जब तक कि आपके Qt सूत्र पायथन कोड को कॉल नहीं करते हैं, उन्हें समवर्ती रूप से चलाने में सक्षम होना चाहिए (विभिन्न संरचनाओं में लागू किए जाने वाले विभिन्न अतिरिक्त ताले को बार कर सकते हैं)।

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

आशा है कि यह आपकी समस्याओं के साथ मदद करता है :)


7
यहां ध्यान देना महत्वपूर्ण है: PyQt QThreads ग्लोबल इंटरप्रेटर लॉक को लेते हैंसभी पायथन कोड GIL को लॉक करते हैं, और आप PyQt में चलने वाले किसी भी क्यूथ्रेड्स को पायथन कोड चला रहे होंगे। (यदि वे वास्तव में आप PyQt के "Py" भाग का उपयोग नहीं कर रहे हैं :)। यदि आप उस पायथन कोड से बाहरी सी लाइब्रेरी में डिफर करना चुनते हैं तो जीआईएल जारी किया जाएगा, लेकिन यह सच है कि आप पायथन धागे या क्यूटी धागे का उपयोग करते हैं।
क्वार्क

यह वास्तव में मैं क्या
संदेश

0

मैं पायथन और पायक्यूट थ्रेड्स के बीच सटीक अंतर पर टिप्पणी नहीं कर सकता, लेकिन मैं वह कर रहा हूं जो आप उपयोग करने का प्रयास कर रहे हैं QThread, QNetworkAcessManagerऔर यह सुनिश्चित करने के लिए कॉल QApplication.processEvents()कर रहे हैं कि धागा जीवित है। यदि GUI जवाबदेही वास्तव में समस्या है जिसे आप हल करने का प्रयास कर रहे हैं, तो बाद में मदद मिलेगी।


1
QNetworkAcessManagerएक धागा की आवश्यकता नहीं है या processEvents। यह एसिंक्रोनस आईओ संचालन का उपयोग करता है।
लुकास लालकिंसी

ओह ... हाँ, मैं QNetworkAcessManagerऔर के संयोजन का उपयोग कर रहा हूँ httplib2। मेरे async कोड का उपयोग करता है httplib2
ब्रायनज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.