[译]如何定义python源文件的文件编码
简介
这篇文章是为了介绍定义python源文件文件编码的方法。python解释器可以根据所指定的编码信息对当前文件进行解析。通常来说,这种方法可以提高解析器对Unicode编码的源文件的识别,并且支持书写Unicode编码,例如在一个支持unicode编码的编辑器中使用UTF-8。
问题
在python2.1中,unicode编码只能通过Latin-1中的“unicode-escape”的方式来实现。这让很多平时不使用Latin-1编码的用户感到非常的不友好,尤其是大多数的亚洲国家更是这样。程序员可以使用他们所习惯的编码来编写8-bit的字符代码,却不得不因为要用到unicode编码而使用"unicode-escape"。
解决方法
我们希望让每一个python文件都可以通过在文件顶端书写一些特定的注释的方法,来实现python源代码编码的可见性和易维护性。
为了让python能够识别出文件编码的定义,需要做一些列关于对python源文件代码数据的扩充。
定义编码
在没有指定其它编码的情况下,python默认使用ASCII作为标准编码。
如果想要定义文件代码编码,一个特殊的注释应该放到源文件的第一或第二行,例如:
# coding=<encoding name>
或(使用一种大多数编辑器都能够识别的方式)
#!/usr/bin/python
# -*- coding: <encoding name> -*-
或
#!/usr/bin/python
# vim: set fileencoding=<encoding name> :
恰好,第一或第二行都完全符合正则表达式“coding[:=]\s*([-\w.]+)”。这个表达式获取到的第一组信息就是编码名称。如果python无法识别编码名称,那么将会在编译完成时报错。在python编码定义的行中,严禁出现python的其它声明。
为了避免一些系统,例如windows,在unicode文件头中增加了文件头标记,UTF-8的签名“\xef\xbb\xbf”同样会作识别文件编码的参照(即使没有设置文件编码注释)。
如果一个源文件既有UTF-8文件头标记,又用注释声明了文件编码,那么此时仅可以声明成“UTF-8”。其它的编码将会导致错误。
示例
以下示例用语说明使用不同的方法,如何在python文件顶端定义python源文件编码。
文件:
1. 利用解释器,并使用Emacs风格的文件编码
注释:
#!/usr/bin/python
# -*- coding: latin-1 -*-
import os, sys
... #!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import os, sys
... #!/usr/bin/python
# -*- coding: ascii -*-
import os, sys
...
2. 不使用解释器,使用一段文字描述
# This Python file uses the following encoding: utf-8
import os, sys
...
3. 文本编辑器中,可以有不同的方式来定义文件的编码,例如:
#!/usr/local/bin/python
# coding: latin-1
import os, sys
...
4. 不使用编码注释,python解释器会将文件当成是ASCII:
#!/usr/local/bin/python
import os, sys
...
5. 不会生效的编码注释:
遗失了“coding:”前缀:
#!/usr/local/bin/python
# latin-1
import os, sys
...
编码注释不在第一和第二行:
#!/usr/local/bin/python
#
# -*- coding: latin-1 -*-
import os, sys
...
不支持的编码:
#!/usr/local/bin/python
# -*- coding: utf-42 -*-
import os, sys
...
理念
我们是根据以下理念来实现的编码注释的用法:
1. 一个python源文件应该具有唯一的编码。内部混杂多种编码数据的行为是不被允许的,并且在编译时会报错。
任意一个能够识别出源码前两行,并且符合以上讨论的编码,都可以作为源码文件的编码,包括ASCII兼容编码和某些多字节编码,如Shift_JIS。所有字符都使用至少两个字节的编码无法被识别,例如UTF-16。这是为了让编码检测算法的检测功能更加简洁。
2. 对于未定义的信息,应该什么都不处理而继续进行分析,就像当前的行为一样。其实所有的可用编码值,都是标准的字符串字符(都是8-bit的Unicode),它们对于其它可能出现在代码中的未定义的信息来说只是很小的一部分。
3. python的 tokenizer/compiler 组件应该被更新为一下的工作流程:
a)读取文件
b)将文件解码成Unicode编码,即一个固定的、假设的编码
c)将文件转换为UTF-8字节字符串
d)tokenize UTF-8化的内容
e)编译,根据给定的Unicode数据创建Unicode对象 ,并且根据文件中给定的编码将UTF-8数据重编码成新的8-bit字符串数据。
注意,python的识别码被限制为了ASCII编码集合,所以在步骤d后不用再对它进行额外的转换。
向下兼容
为了兼容已存在的,没有使用ASCII编码并且没有声明编码格式的,现在需要进行2步来进行使用:
1. 将所有不使用ASCII编码并且没有做注释的文件,将它们当作丢失了“iso-8859-1”定义。这会导致强行将字节字符串的处理放置到步骤2-5之前,并且在python2.2中,提升了对非ASCII字符——Unicode的兼容。
当发现输入文件没有ASCII字节时,会在编码输入文件的时候产生一个警告。
2. 删除警告,并将默认编码格式设置为“ASCII”。
内建compile() API,用来提高对输入文件为Unicode编码时的处理能力。字节字符串的输入的处理方式在上文中已经进行过描述。
如果一个带有编码声明的字符串传递给了compile(),那么将会发生一个SyntaxError。
SUZUKI Hisao可以通过使用patch来兼容,查看[2]获取更多信息。
只有在第一步可以使用的patch,在[1]。
新进展
向下兼容中的步骤1和2已经在2.3版本中进行了完善,除了将默认编码置为“ascii”。
在2.5版本中,实现了将默认编码设置成“ascii”。
链接
[1] Phase 1 implementation:
http://python.org/sf/526840
[2] Phase 2 implementation:
http://python.org/sf/534304
历史
1.10 and above: see CVS history
1.8: Added '.' to the coding RE.
1.7: Added warnings to phase 1 implementation. Replaced the
Latin-1 default encoding with the interpreter's default
encoding. Added tweaks to compile().
1.4 - 1.6: Minor tweaks
1.3: Worked in comments by Martin v. Loewis:
UTF-8 BOM mark detection, Emacs style magic comment,
two phase approach to the implementation
版权
This document has been placed in the public domain.
Source: https://hg.python.org/peps/file/tip/pep-0263.txt
[译]如何定义python源文件的文件编码的更多相关文章
- [译]一个灵活的 Trello 敏捷工作流
[译]一个灵活的 Trello 敏捷工作流 翻译自 An Agile Trello Workflow That Keeps Tasks Flexible Getting things done 可不只 ...
- python读取中文文件编码问题
python 读取中文文件后,作为参数使用,经常会遇到乱码或者报错asii错误等. 我们需要对中文进行decode('gbk') 如我有一个data.txt文件有如下内容: 百度 谷歌 现在想读取文件 ...
- [译]如何使用 Docker 组件开发 Django 项目?
原文地址:Django Development With Docker Compose and Machine 以下为译文 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包 ...
- [转]iOS证书(.p12)和描述文件(.mobileprovision)申请
转载于:http://ask.dcloud.net.cn/article/152 iOS有两种证书和描述文件: 证书类型 使用场景 开发(Development)证书和描述文件 用于开发测试,在HBu ...
- [caffe]linux下安装caffe(无cuda)以及python接口
昨天在mac上折腾了一天都没有安装成功,晚上在mac上装了一个ParallelDesktop虚拟机,然后装了linux,十分钟就安装好了,我也是醉了=.= 主要过程稍微记录一下: 1.安装BLAS s ...
- [Swift]基础
[Swift]基础 一, 常用变量 var str = "Hello, playground" //变量 let str1="Hello xmj112288" ...
- [Ruby on Rails系列]4、专题:Rails应用的国际化[i18n]
1. 什么是internationalization(i18n)? 国际化,英文简称i18n,按照维基百科的定义:国际化是指在设计软件,将软件与特定语言及地区脱钩的过程.当软件被移植到不同的语言及地区 ...
- Java基础 之软引用、弱引用、虚引用 ·[转载]
Java基础 之软引用.弱引用.虚引用 ·[转载] 2011-11-24 14:43:41 Java基础 之软引用.弱引用.虚引用 浏览(509)|评论(1) 交流分类:Java|笔记分类: Ja ...
- MongoDB入门教程三[数据类型]
MongoDB的文档使用BSON(Binary JSON)来组织数据,BSON类似于JSON,JSON只是一种简单的表示数据的方式,只包含了6种数据类型(null.布尔.数字.字符串.数组及对象),不 ...
随机推荐
- Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...
- .NET的对象映射工具AutoMapper使用笔记
AutoMapper是一个.NET的对象映射工具. 项目地址:https://github.com/AutoMapper/AutoMapper. 帮助文档:https://github.com/Aut ...
- 中文字符 unicode转utf-8函数 python实现
unicode编码范围 00000000-0000007F的字符,用单个字节来表示: 00000080-000007FF的字符用两个字节表示 (中文的编码范围) 00000800-0000FFFF的字 ...
- Linux下gcc编译生成动态链接库*.so文件并调用它 是转载的
动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一 ...
- 配置 nginx location 实时查看 php-fpm 的状态
在Nginx.conf 里配置 location ~ ^/status$ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_ ...
- HDU 4044 GeoDefense
树形DP,和背包差不多.dp[now][x]表示now这个节点的子树上,花费为x的时候,获得的最大防御能力(保证敌方HP<=0) #include<cstdio> #include& ...
- STM32的NVIC_PriorityGroupConfig使用及优先级分组方式理解
STM32的NVIC_PriorityGroupConfig使用及优先级分组方式理解 STM32的优先级NVIC_PriorityGroupConfig的理解及其使用 STM32中断优先级彻底讲解 S ...
- KERMIT,XMODEM,YMODEM,ZMODEM传输协议小结(转)
源:KERMIT,XMODEM,YMODEM,ZMODEM传输协议小结 Kermit协议 报文格式: 1.MARK,起始标记START_CHAR,为 0x01(CTRIL-A): 2.LEN,报文剩余 ...
- beamer中插入c代码,python代码的经验
下面是插入的scala代码,它与python在某些语法上类似,所在在https://github.com/olivierverdier/python-latex-highlighting下载了一个py ...
- mongodbVUE基本操作(转)
基本操作: http://my.oschina.net/u/1026531/blog/188336