繁体   English   中英

在源代码中使用Unicode字符运行Python 2.7代码

[英]Running Python 2.7 Code With Unicode Characters in Source

我想运行在源代码中包含unicode(utf-8)字符的Python源文件。 我知道可以通过在开头添加注释# -*- coding: utf-8 -*-来完成这一事实。 但是,我希望不使用此方法。

我能想到的一种方法是以转义形式编写unicode字符串。 例如,

编辑:更新源。 添加了Unicode注释。

# Printing naïve and 男孩
def fxn():
    print 'naïve'
    print '男孩'
fxn()

# Printing na\xc3\xafve and \xe7\x94\xb7\xe5\xad\xa9
def fxn():
    print 'na\xc3\xafve'
    print '\xe7\x94\xb7\xe5\xad\xa9'
fxn()

关于上述方法,我有两个问题。

  1. 如何使用Python将第一个代码段转换为跟在其后的等效代码段? 也就是说,仅unicode序列应以转义形式编写。
  2. 仅考虑使用Unicode(utf-8)字符的方法是否万无一失? 有什么地方可能出问题吗?

您的想法通常是正确的,但会在Python 3中中断,并且在Python 2中操作和编写字符串时会引起头痛。

在处理非ASCII时,最好使用Unicode字符串,而不是常规字符串。

相反,您可以将字符编码为Unicode字符串中的Unicode (不是UTF-8)转义序列。

u'na\xefve'
u'\u7537\u5b69'

注意u前缀

您的代码现已编码不可知。

如果仅使用字节字符串,并且将您的源文件保存为UTF-8编码,则您的字节字符串包含UTF-8编码的数据。 不需要编码语句(尽管很奇怪,您不想使用它……这只是一条注释)。 编码语句使Python知道源文件的编码,因此它可以正确解码Unicode字符串( u'xxxxx' )。 如果没有Unicode字符串,那就没关系。

对于您的问题,无需转换为转义码。 如果将文件编码为UTF-8,则可以在字节字符串中使用可读性更高的字符。

仅供参考,这不适用于Python 3,因为字节字符串在该版本中不能包含非ASCII。

就是说,这里有一些代码将按要求转换您的示例。 假定源代码以UTF-8编码,它将读取源代码,然后使用正则表达式查找所有非ASCII字符。 它将它们传递给转换函数以生成替换。 这应该是安全的,因为非ASCII只能在Python 2中用于字符串文字和常量中。但是,Python 3允许在变量名中使用非ASCII,因此在此不起作用。

import io
import re

def escape(m):
    char = m.group(0).encode('utf8')
    return ''.join(r'\x{:02x}'.format(ord(b)) for b in char)

with io.open('sample.py',encoding='utf8') as f:
    content = f.read()

new_content = re.sub(r'[^\x00-\x7f]',escape,content)

with io.open('sample_new.py','w',encoding='utf8') as f:
    f.write(new_content)

结果:

# Printing na\xc3\xafve and \xe7\x94\xb7\xe5\xad\xa9
def fxn():
    print 'na\xc3\xafve'
    print '\xe7\x94\xb7\xe5\xad\xa9'
fxn()

问题1:

尝试使用:

print u'naïve'

print u'长者'

问题2:

如果您使用键盘和中文输入软件输入句子,则一切正常。 但是,如果您从某些网页复制和粘贴句子,则应考虑其他编码格式,例如GBKGB2312GB18030

Python 3的此代码片段应正确转换您的程序以在Python 2中工作。

def convertchar(char): #converts individual characters
    if 32<=ord(char)<=126 or char=="\n": return char #if normal character, return it
    h=hex(ord(char))[2:]
    if ord(char)<256: #if unprintable ASCII
        h=" "*(2-len(h))+h
        return "\\x"+h
    elif ord(char)<65536: #if short unicode
        h=" "*(4-len(h))+h
        return "\\u"+h
    else: #if long unicode
        h=" "*(8-len(h))+h
        return "\\U"+h

def converttext(text): #converts a chunk of text
    newtext=""
    for char in text:
        newtext+=convertchar(char)
    return newtext

def convertfile(oldfilename,newfilename): #converts a file
    oldfile=open(oldfilename,"r")
    oldtext=oldfile.read()
    oldfile.close()
    newtext=converttext(oldtext)
    newfile=open(newfilename,"w")
    newfile.write(newtext)
    newfile.close()

convertfile("FILE_TO_BE_CONVERTED","FILE_TO_STORE_OUTPUT")

首先简单回顾一下:当您在Python2脚本中使用字节字符串时, # -*- coding: utf-8 -*-完全无效。 如果您编写了以下代码,则仅有助于将源字节字符串转换为unicode字符串:

# -*- coding: utf-8 -*-
...
utxt = u'naïve' # source code is the bytestring `na\xc3\xafve'
                # but utxt must become the unicode string u'na\xefve'

简单地,聪明的编辑器可能会解释为自动使用utf8字符集。

现在是实际问题。 不幸的是,您要的内容并不是很简单:在源文件中识别注释和字符串中的内容仅需要Python解析器...而且AFAIK,如果您使用ast模块的解析器,您将失去注释除了文档字符串。

但是在Python 2中,非ASCII字符只能在注释和乱码中使用! 因此,您可以放心地假设,如果源文件是不包含乱码unicode字符串(*)的正确Python 2脚本,则可以安全地以其Python表示形式转换任何非ascii字符。

一个可能的Python函数从一个文件对象读取原始源文件,并在另一个文件对象中进行编码后将其写入:

def src_encode(infile, outfile):
    while True:
        c = infile.read(1)
        if len(c) < 1: break  # stop on end of file
        if ord(c) > 127:      # transform high characters
            c = "\\x{:2x}".format(ord(c))
        outfile.write(c)

一个不错的特性是,只要源文件被Python解释器接受并且在Unicode乱码(*)中不包含高位字符,并且转换后的文件的行为与原始文件完全相同,它就可以使用您使用的任何编码。 。


(*)如果您在Unicode之外的其他编码中使用Unicode乱码,则会出现问题,因为上述函数的行为就像文件中包含声明# -*- coding: Latin1 -*-u'é'将被翻译如果原始编码是latin1,则正确地表示为u'\\xe9' ,但是如果原始编码是utf8,则正确地显示为u'\\xc3\\xc9' (不是预期的结果...),我无法想象一种正确处理两个字节字节字符串和未完全解析源文件的unicode字节字符串...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM