2016-07-01 22 views
8

यह काफी एक आम गलती का उपयोग कर datetime.strptime() प्रारूप स्ट्रिंग और दिनांक स्ट्रिंग तर्क अप मिश्रण है:मिश्रण datetime.strptime() तर्क

datetime.strptime("%B %d, %Y", "January 8, 2014") 
बजाय दूसरी तरह के आसपास के

:

datetime.strptime("January 8, 2014", "%B %d, %Y") 

बेशक, यह रनटाइम के दौरान विफल हो जाएगा:

>>> datetime.strptime("%B %d, %Y", "January 8, 2014") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 325, in _strptime 
    (data_string, format)) 
ValueError: time data '%B %d, %Y' does not match format 'January 8, 2014' 

लेकिन, यह इस समर्थक को पकड़ने के लिए संभव है वास्तव में कोड चलाने से पहले ब्लेम सांख्यिकीय रूप से? क्या यह pylint या flake8 मदद कर सकता है?


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

+0

alecxe, आम तौर पर यदि हम एक स्ट्रिंग को डेटाटाइम में कनवर्ट करना चाहते हैं तो हम स्ट्रिंगटाइम() को विशेष स्ट्रिंग पर इस्तेमाल करेंगे, स्ट्रेटटाइम के अलावा हम स्ट्रिंग को नियमित अभिव्यक्तियों के साथ जांच सकते हैं यदि दिया गया स्ट्रिंग उचित डेटाटाइम प्रारूप में है या नहीं, लेकिन यह जांच करने के लिए और अधिक नियमित अभिव्यक्ति पैटर्न ले जाएगा। – MicroPyramid

उत्तर

18

मेरा दावा है कि इसे सामान्य मामले सामान्य मामले में चेक नहीं किया जा सकता है।

निम्नलिखित स्निपेट पर विचार करें:

d = datetime.strptime(read_date_from_network(), read_format_from_file()) 

इस कोड को पूरी तरह से मान्य हो सकता है, जहां दोनों read_date_from_network और read_format_from_file वास्तव में उचित प्रारूप का सूत्र है - या वे कुल कचरा, दोनों लौटने कोई नहीं या कुछ हो सकता है बकवास। भले ही, वह जानकारी केवल रनटाइम पर निर्धारित की जा सकती है - इसलिए, एक स्थिर परीक्षक शक्तिहीन है।


इतना ही नहीं, datetime.strptime की वर्तमान परिभाषा दी है, भले ही हम एक स्थिर टाइप किया भाषा का प्रयोग, हम (बहुत विशिष्ट मामलों को छोड़कर) इस त्रुटि को पकड़ने के लिए सक्षम नहीं होगा थे - कारण किया जा रहा है कि इस समारोह के हस्ताक्षर शुरू से हमें बर्बाद:

classmethod datetime.strptime(date_string, format) 
इस परिभाषा में

, date_string और format दोनों तार हैं, यहां तक ​​कि वे actuall हालांकि वाई का विशेष अर्थ है। यहां तक ​​कि अगर हम इस तरह एक स्थिर टाइप किया भाषा में कुछ अनुरूप था:

public DateTime strpTime(String dateString, String format) 

संकलक (और लिंटर और बाकी सब) अभी भी केवल देखता है:

public DateTime strpTime(String, String) 

जिसका मतलब है कि निम्न में से कोई भी अलग पहचानी एक दूसरे से:

strpTime("%B %d, %Y", "January 8, 2014") // strpTime(String, String) CHECK 
strpTime("January 8, 2014", "%B %d, %Y") // strpTime(String, String) CHECK 
strpTime("cat", "bat") // strpTime(String, String) CHECK 

यह नहीं कहा जा रहा है कि यह कम से नहीं किया जा सकता सब - जावा/सी ++/आदि जैसे स्थिर टाइप की गई भाषाओं के लिए कुछ लिंटर्स मौजूद हैं। जब आप उन्हें कुछ विशिष्ट कार्यों (जैसे printf, आदि) में पास करते हैं तो स्ट्रिंग अक्षर का निरीक्षण करेंगे।), लेकिन यह केवल तब किया जा सकता है जब आप उस फ़ंक्शन को सीधे शाब्दिक प्रारूप स्ट्रिंग के साथ कॉल कर रहे हों। मेरे द्वारा प्रस्तुत किए गए पहले मामले में वही लिंटर्स उतना ही असहाय हो जाते हैं, क्योंकि यह अभी तक ज्ञात नहीं है कि तार सही प्रारूप होंगे या नहीं।

एक लिंटर यानी इस बारे में चेतावनी देने के लिए सक्षम हो सकता है:

// Linter regex-es the first argument, sees %B et. al., warns you 
strpTime("%B %d, %Y", "January 8, 2014") 

लेकिन यह इस बारे में चेतावनी देने के लिए सक्षम नहीं होगा:

strpTime(scanner.readLine(), scanner.readLine()) 

अब, उसी एक अजगर में इंजीनियर किया जा सकता है लिटर, लेकिन मुझे विश्वास नहीं है कि यह बहुत उपयोगी होगा क्योंकि फ़ंक्शंस प्रथम श्रेणी हैं, इसलिए मैं लिखकर आसानी से (काल्पनिक पाइथन) लिटर को पराजित कर सकता हूं:

f = datetime.strptime 
d = f("January 8, 2014", "%B %d, %Y") 

और फिर हम फिर से बहुत ज्यादा परेशान हैं।


बोनस: यहाँ क्या गलत हो गया

समस्या यह है कि datetime.strptime इन तार से प्रत्येक के लिए निहित अर्थ देता है, लेकिन यह प्रकार व्यवस्था करने के लिए है कि जानकारी की सतह नहीं है। क्या किया जा सकता था दो तार अलग-अलग प्रकार देने के लिए - तो कुछ आसानी से उपयोग की कीमत पर यद्यपि अधिक सुरक्षा हो सकती थी।

जैसे (का उपयोग कर पीईपी 484 प्रकार एनोटेशन, a real thing!):

class DateString(str): 
    pass 

class FormatString(str): 
    pass 

class datetime(date): 
    ... 
    def strptime(date_string: DateString, format: FormatString) -> datetime: 
    # etc. etc. 

तो यह संभव हो के लिए शुरू सामान्य मामले में अच्छा linting प्रदान करने के लिए होता है - हालांकि डेटस्ट्रिंग और FormatString कक्षाएं देखभाल करने के लिए की आवश्यकता होगी अपने इनपुट को प्रमाणित करने के लिए, क्योंकि फिर से, टाइप सिस्टम उस स्तर पर कुछ भी नहीं कर सकता है।


अंतभाषण:

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

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