python - meaning - obtener la codificación especificada en la línea mágica/shebang(desde dentro del módulo)
shebang meaning (1)
Pediría prestada la función Python 3 tokenize.detect_encoding()
en Python 2, ajustada un poco para que coincida con las expectativas de Python 2. Cambié la firma de la función para aceptar un nombre de archivo y dejé de incluir las líneas leídas hasta el momento; no los necesita para su uso:
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
Al igual que la función original, la función anterior lee dos líneas como máximo desde el archivo fuente, y generará una excepción SyntaxError
si la codificación en la cookie no es válida o no es UTF-8 mientras está presente una BOM UTF-8.
Manifestación:
>>> 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
Si especifico la codificación de caracteres (como lo sugiere PEP 263 ) en la "línea mágica" o shebang de un módulo python como
# -*- coding: utf-8 -*-
¿Puedo recuperar esta codificación desde ese módulo?
(Trabajando en Windows 7 x64 con Python 2.7.9)
Intenté (sin éxito) recuperar la codificación predeterminada o shebang
# -*- coding: utf-8 -*-
import sys
from shebang import shebang
print "sys.getdefaultencoding():", sys.getdefaultencoding()
print "shebang:", shebang( __file__.rstrip("oc"))
rendirá:
sys.getdefaultencoding (): ascii
shebang: Ninguno
(lo mismo para iso-8859-1)