2016-07-14 4 views
6

अगर मैं वर्ण एन्कोडिंग (के रूप में PEP 263 ने सुझाव दिया) निर्दिष्ट जादू लाइन/कुटिया में निर्दिष्ट एन्कोडिंग प्राप्त कर सकते हैं मैं उस मॉड्यूल के भीतर से इस एन्कोडिंग को पुनः प्राप्त करें?</p> <pre><code># -*- coding: utf-8 -*- </code></pre> <p>की तरह "जादू लाइन" या एक अजगर मॉड्यूल के कुटिया में (मॉड्यूल के भीतर से)

डिफ़ॉल्ट एन्कोडिंग या कुटिया

# -*- coding: utf-8 -*- 

import sys 
from shebang import shebang 

print "sys.getdefaultencoding():", sys.getdefaultencoding() 
print "shebang:", shebang(__file__.rstrip("oc")) 

निकलेगा पुनः प्राप्त करने के


मैंने कोशिश की (सफलता के बिना) (अजगर 2.7.9 के साथ विंडोज 7 x64 पर कार्य करना):

sys.getdefaultencoding(): ascii

shebang: None

(आईएसओ -885 9 -1 के लिए समान)

+1

यह बहुत संभव है कि एन्कोडिंग जानकारी 'pyc' के संकलन के बाद खो जाता है। आपको सीधे 'py' फ़ाइल को पार्स करने की आवश्यकता हो सकती है। – gdlmx

+2

ध्यान दें कि 'sys.getdefaultencoding() 'में कुछ भी नहीं है * पाइथन स्रोत कोड को कैसे डीकोड किया गया है। –

उत्तर

5

मैं पाइथन 2 में पायथन 3 tokenize.detect_encoding() function उधार लेता हूं, पाइथन 2 अपेक्षाओं से मेल खाने के लिए थोड़ा समायोजित करता हूं। मैंने फ़ाइल नाम स्वीकार करने के लिए फ़ंक्शन हस्ताक्षर को बदल दिया है और अब तक पढ़ने वाली लाइनों को शामिल करने को छोड़ दिया है; आप अपने USECASE के लिए उन की जरूरत नहीं है:

import re 
from codecs import lookup, BOM_UTF8 

cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)') 
blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)') 

def _get_normal_name(orig_enc): 
    """Imitates get_normal_name in tokenizer.c.""" 
    # Only care about the first 12 characters. 
    enc = orig_enc[:12].lower().replace("_", "-") 
    if enc == "utf-8" or enc.startswith("utf-8-"): 
     return "utf-8" 
    if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ 
     enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): 
     return "iso-8859-1" 
    return orig_enc 

def detect_encoding(filename): 
    bom_found = False 
    encoding = None 
    default = 'ascii' 

    def find_cookie(line): 
     match = cookie_re.match(line) 
     if not match: 
      return None 
     encoding = _get_normal_name(match.group(1)) 
     try: 
      codec = lookup(encoding) 
     except LookupError: 
      # This behaviour mimics the Python interpreter 
      raise SyntaxError(
       "unknown encoding for {!r}: {}".format(
        filename, encoding)) 

     if bom_found: 
      if encoding != 'utf-8': 
       # This behaviour mimics the Python interpreter 
       raise SyntaxError(
        'encoding problem for {!r}: utf-8'.format(filename)) 
      encoding += '-sig' 
     return encoding 

    with open(filename, 'rb') as fileobj:   
     first = next(fileobj, '') 
     if first.startswith(BOM_UTF8): 
      bom_found = True 
      first = first[3:] 
      default = 'utf-8-sig' 
     if not first: 
      return default 

     encoding = find_cookie(first) 
     if encoding: 
      return encoding 
     if not blank_re.match(first): 
      return default 

     second = next(fileobj, '') 

    if not second: 
     return default  
    return find_cookie(second) or default 

मूल कार्य की तरह, ऊपर समारोह दो पंक्तियों स्रोत फ़ाइल से अधिकतम पढ़ता है, और एक SyntaxError अपवाद बढ़ा देंगे अगर कुकी में एन्कोडिंग अमान्य है या यूटीएफ -8 नहीं है जबकि यूटीएफ -8 बीओएम मौजूद है।

डेमो:

>>> import tempfile 
>>> def test(contents): 
...  with tempfile.NamedTemporaryFile() as f: 
...   f.write(contents) 
...   f.flush() 
...   return detect_encoding(f.name) 
... 
>>> test('# -*- coding: utf-8 -*-\n') 
'utf-8' 
>>> test('#!/bin/env python\n# -*- coding: latin-1 -*-\n') 
'iso-8859-1' 
>>> test('import this\n') 
'ascii' 
>>> import codecs 
>>> test(codecs.BOM_UTF8 + 'import this\n') 
'utf-8-sig' 
>>> test(codecs.BOM_UTF8 + '# encoding: latin-1\n') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in test 
    File "<string>", line 37, in detect_encoding 
    File "<string>", line 24, in find_cookie 
SyntaxError: encoding problem for '/var/folders/w0/nl1bwj6163j2pvxswf84xcsjh2pc5g/T/tmpxsqH8L': utf-8 
>>> test('# encoding: foobarbaz\n') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in test 
    File "<string>", line 37, in detect_encoding 
    File "<string>", line 18, in find_cookie 
SyntaxError: unknown encoding for '/var/folders/w0/nl1bwj6163j2pvxswf84xcsjh2pc5g/T/tmpHiHdG3': foobarbaz 
+0

ग्रेट कोड, हालांकि विंडोज़ पर यह मुझे 'IOError देता है: [Errno 13] अनुमति अस्वीकार कर दी गई: 'c: \\ users \\ maggyero \\ appdata \\ local \\ temp \\ tmp6qsaxo'' (लिनक्स पर यह ठीक काम करता है)। मेरे पास एक संबंधित प्रश्न है [यहां] (https://stackoverflow.com/questions/48984214/python-2-assumes- अलग- स्रोत-code-encodings) और मुझे लगता है कि आप उत्तर देने के लिए यहां सबसे योग्यता में से एक हैं। – Maggyero

+1

@ मैग्गीरो: यह विंडोज़ पर ['नामांकित समकालीनफाइल 'वर्ग] (https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile) की सीमा है: * क्या नाम खोलने के लिए उपयोग किया जा सकता है दूसरी बार फ़ाइल, जबकि नामित अस्थायी फ़ाइल अभी भी खुली है, प्लेटफार्मों में भिन्न होती है (इसे यूनिक्स पर इतना उपयोग किया जा सकता है; यह विंडोज एनटी या बाद में नहीं हो सकता है)। * –

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