2009-10-08 13 views
10

समस्या:पाइथन मल्टीप्रोसेसिंग और पीओडीबीसी के साथ डेटाबेस एक्सेस "सुरक्षित नहीं है"?

मैं निम्नलिखित ट्रैसबैक हो रही है और समझ में नहीं आता कि इसका क्या मतलब है या यह कैसे तय करने के लिए:

Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "C:\Python26\lib\multiprocessing\forking.py", line 342, in main 
    self = load(from_parent) 
    File "C:\Python26\lib\pickle.py", line 1370, in load 
    return Unpickler(file).load() 
    File "C:\Python26\lib\pickle.py", line 858, in load 
    dispatch[key](self) 
    File "C:\Python26\lib\pickle.py", line 1083, in load_newobj 
    obj = cls.__new__(cls, *args) 
TypeError: object.__new__(pyodbc.Cursor) is not safe, use pyodbc.Cursor.__new__() 

स्थिति:

मैंने संसाधित होने के लिए डेटा से भरा SQL सर्वर डेटाबेस मिला। मैं काम को समानांतर करने के लिए मल्टीप्रोसेसिंग मॉड्यूल का उपयोग करने की कोशिश कर रहा हूं और अपने कंप्यूटर पर एकाधिक कोर का लाभ उठा रहा हूं। यह मुख्य वर्ग है, जहां कार्यक्रम शुरू होता है

  • MyManagerClass
    • : मेरी सामान्य वर्ग संरचना इस प्रकार है।
    • यह दो multiprocessing.Queue वस्तुओं, एक work_queue और एक write_queue
    • यह भी बनाता है और अन्य प्रक्रियाओं की शुरूआत है, तो उसके पूरा करने तक इंतजार कर रहा है बनाता है।
    • नोट: इस नहीं multiprocessing.managers.BaseManager का ही विस्तार()
  • MyReaderClass
    • इस वर्ग एसक्यूएल सर्वर डेटाबेस से डेटा पढ़ता है।
    • यह आइटम work_queue में रखता है।
  • MyWorkerClass
    • यह जहां काम प्रसंस्करण होता है।
    • यह work_queue से आइटम प्राप्त करता है और write_queue में पूरा आइटम डालता है।
  • MyWriterClass
    • इस वर्ग संसाधित डेटा वापस एसक्यूएल सर्वर डेटाबेस के लिए लिखने की ज़िम्मेदारी है।
    • यह write_queue से आइटम प्राप्त करता है।

विचार यह है कि वहाँ एक प्रबंधक, एक रीडर, एक लेखक, और कई श्रमिकों हो जाएगा।

अन्य विवरण:

मैं stderr में दो बार ट्रैस बैक मिलता है, तो मैं सोच रहा हूँ कि यह लेखक के लिए पाठक के लिए एक बार होता है और एक बार। मेरी कार्यकर्ता प्रक्रियाएं ठीक हो जाती हैं, लेकिन जब तक मैं एक कीबोर्ड इंटरप्ट भेजता हूं तब तक बस बैठें क्योंकि उनके पास work_queue में कुछ भी नहीं है।

दोनों पाठक और लेखक के पास डेटाबेस पर अपना कनेक्शन है, जो प्रारंभिकरण पर बनाया गया है।

समाधान: कि इस समाधान के लिए नेतृत्व उनके जवाब और प्रश्नों के लिए मार्क और फर्डिनेंड बेयर को

धन्यवाद। उन्होंने सही ढंग से बताया कि कर्सर ऑब्जेक्ट "अचार-सक्षम" नहीं है, जो प्रक्रिया है जो मल्टीप्रोसेसिंग प्रक्रियाओं के बीच जानकारी पास करने के लिए उपयोग करती है।

मेरे कोड के साथ समस्या यह थी कि MyReaderClass(multiprocessing.Process) और MyWriterClass(multiprocessing.Process) दोनों अपने __init__() विधियों में डेटाबेस से जुड़े थे। मैंने MyManagerClass में इन दोनों ऑब्जेक्ट्स (यानी उनकी इनिट विधि कहा) बनाया, फिर start() कहा जाता है।

तो यह कनेक्शन और कर्सर ऑब्जेक्ट्स बनाएगा, फिर उन्हें अचार के माध्यम से बाल प्रक्रिया में भेजने का प्रयास करें। मेरा समाधान कनेक्शन (कर्सर ऑब्जेक्ट्स को रन() विधि के तत्कालता को स्थानांतरित करना था, जिसे तब तक नहीं कहा जाता जब तक कि बच्चे की प्रक्रिया पूरी तरह से बनाई जाती न हो।

+0

बस कहने के लिए: उत्कृष्ट प्रश्न। – mavnn

उत्तर

8

मल्टीप्रोसेसिंग प्रक्रियाओं के बीच वस्तुओं को संवाद करने के लिए पिकलिंग पर निर्भर करता है। Pyodbc कनेक्शन और कर्सर वस्तुओं को मसालेदार नहीं किया जा सकता है।

>>> cPickle.dumps(aCursor) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python2.5/copy_reg.py", line 69, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle Cursor objects 
>>> cPickle.dumps(dbHandle) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python2.5/copy_reg.py", line 69, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle Connection objects 

"यह आइटम को work_queue में रखता है", क्या आइटम? क्या यह संभव है कि कर्सर ऑब्जेक्ट भी पास हो रहा है?

+0

मेरे पास एक जेनरेटर है जो कर्सर में आइटम्स पर लूप करता है (मूल रूप से pyodbyc.Cursor()। Fetchone() को कॉल करता है। मेरा मानना ​​है कि यह एक tuple (आईडी, stuff_to_process) पैदा करता है जो मैंने कतार में रखा है। मैंने एक गहरी आवाज बनाने की कोशिश की, लेकिन यह काम नहीं किया। मैंने मदद को देखा और यह वास्तव में पंक्ति वस्तु का एक उदाहरण है। तो मुझे पहले एक ट्यूपल में बदलने की आवश्यकता हो सकती है। – tgray

+0

पंक्ति वस्तु में कर्सर या कुछ का संदर्भ होना चाहिए। – tgray

+0

पंक्ति को एक टुपल में कनवर्ट करने से इसे हल नहीं किया गया। – tgray

3

त्रुटि pickle मॉड्यूल के भीतर उठाई गई है, इसलिए कहीं भी आपकी डीबी-कर्सर ऑब्जेक्ट मसालेदार और अनपिक्स्ड हो जाती है (स्टोरेज को क्रमबद्ध किया जाता है और पाइथन ऑब्जेक्ट को फिर से नहीं किया जाता है)।

मुझे लगता है कि pyodbc.Cursor पिकलिंग का समर्थन नहीं करता है। आप कर्सर ऑब्जेक्ट को वैसे भी जारी रखने की कोशिश क्यों कर सकते हैं?

जांचें कि क्या आप अपनी कार्य श्रृंखला में pickle का उपयोग करते हैं या यदि इसका उपयोग पूरी तरह से किया जाता है।

+0

ऐसा लगता है कि मल्टीप्रोसेसिंग प्रक्रियाओं के बीच पाइप ऑब्जेक्ट्स (विशेष रूप से बनाई गई कतार वस्तुओं) के बीच चीजों को पारित करने के लिए इसका उपयोग करती है। – tgray

1

pyodbc में पायथन डीबी-एपीआई threadsafety level 1 है। इसका मतलब है कि धागे कनेक्शन साझा नहीं कर सकते हैं, और यह थ्रेडसेफ बिल्कुल नहीं है।

मुझे नहीं लगता कि अंतर्निहित थ्रेड-सुरक्षित ओडीबीसी ड्राइवर एक फर्क पड़ता है। यह पाइथन कोड में है जैसा कि पिकलिंग त्रुटि द्वारा नोट किया गया है।

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