मैं अपने कोड को Python2 से Python3 में माइग्रेट करने का प्रयास कर रहा हूं क्योंकि Python2 अब समर्थित नहीं है।
हालाँकि मुझे दो संस्करणों के बीच अंतर के कारण माइग्रेशन प्रक्रिया में कठिनाइयाँ आ रही हैं। मुझे पता है कि Python2 में स्ट्रिंग और यूनिकोड दोनों ऑब्जेक्ट हुआ करते थे, जबकि Python3 स्ट्रिंग्स का डिफ़ॉल्ट स्टोरेज यूनिकोड है।

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

मेरी समस्या दिखाने वाला एक कोड स्निपेट यहां दिया गया है:

पायथन2 -

In [1]: from hashlib import sha1

In [2]: cred = ('user', 'pass')

In [3]: sha1(str(cred)).hexdigest()
Out[3]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'

In [4]: unicode_cred = ('user', u'pass')

In [5]: sha1(str(unicode_cred)).hexdigest()
Out[5]: '807a138ff9b0dd6ce6a937e3df3bba3223b40fcd'

पायथन3 -

In [1]: from hashlib import sha1                                                

In [2]: cred = ('user', 'pass')                                                 

In [3]: sha1(str(cred)).hexdigest()                                             
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-847e91fdf4c5> in <module>
----> 1 sha1(str(cred)).hexdigest()

TypeError: Unicode-objects must be encoded before hashing

In [4]: sha1(str(cred).encode('utf-8')).hexdigest()                             
Out[4]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'

In [5]: unicode_cred = ('user', u'pass')                                        

In [6]: sha1(str(unicode_cred).encode('utf-8')).hexdigest()                     
Out[6]: '7cd99ee437e8166559f55a0336d4b48d9bc62bb2'

जैसा कि आप देख सकते हैं, Python2 में Out[3] का मान Out[5] की तुलना में भिन्न है, जबकि Python3 में Out[4] और Out[6] समान हैं।

क्या Python2 स्निपेट में दिखाए गए Out[5] के मान को पुन: पेश करने का कोई तरीका है?
माइग्रेशन प्रक्रिया के हिस्से के रूप में, मुझे यह सुनिश्चित करने की ज़रूरत है कि वही इनपुट समान आउटपुट उत्पन्न करता है, इसलिए मैं मौजूदा डेटाबेस को अपडेट करने के बजाय अपने डेटाबेस में एक नया रिकॉर्ड नहीं डालूंगा।

0
Matan Itzhak 29 मार्च 2020, 00:23

1 उत्तर

सबसे बढ़िया उत्तर

str() आउटपुट के हेक्स डाइजेस्ट का उपयोग करना समस्या है। str() एक संस्करण-निर्भर स्ट्रिंग है और हेक्स डाइजेस्ट बनाने के लिए आपको ठीक उसी प्रतिनिधित्व की आवश्यकता है:

अजगर २

>>> unicode_cred = ('user', u'pass')
>>> str(unicode_cred)
"('user', u'pass')"

पायथन 3 (लापता 'यू' पर ध्यान दें)। str() का आउटपुट भी Python 3 पर एक यूनिकोड स्ट्रिंग है, इसलिए इसे sha1() के साथ उपयोग करने के लिए बाइट्स में एन्कोड किया जाना चाहिए। b स्ट्रिंग का हिस्सा नहीं है, लेकिन सिर्फ यह दर्शाता है कि यह अब एक बाइट स्ट्रिंग है।

>>> unicode_cred = ('user', u'pass')
>>> str(unicode_cred).encode('utf-8')
b"('user', 'pass')"

समान डाइजेस्ट प्राप्त करने के लिए आपको u के साथ एक ही स्ट्रिंग बनाने की आवश्यकता होगी, और यह थोड़ा बदसूरत है। यहां मैं एक u के साथ टपल को कस्टम प्रारूपित करने के लिए एक एफ-स्ट्रिंग का उपयोग करता हूं। मैं ascii के साथ भी एन्कोड करता हूं क्योंकि गैर-ASCII वर्ण एक अतिरिक्त समस्या पैदा करेंगे। उम्मीद है कि आपके पास गैर-ASCII वाले उपयोगकर्ता नाम और पासवर्ड नहीं हैं।

>>> from hashlib import sha1
>>> unicode_cred = ('user', u'pass')
>>> f"('{unicode_cred[0]}', u'{unicode_cred[1]}')"
"('user', u'pass')"
>>> sha1(f"('{unicode_cred[0]}', u'{unicode_cred[1]}')".encode('ascii')).hexdigest()
'807a138ff9b0dd6ce6a937e3df3bba3223b40fcd'
1
Mark Tolonen 29 मार्च 2020, 07:37