python渐进-把代码放到文件里

之前的代码片段都是在python解析器的交互界面进行的。为了能让python代码重复使用,需要把代码保存到一个文件中。以后就可以继续使用这些代码了。

9.1代码文件的保存和运行

代码文件的保存很简单,就是直接把之前敲过的代码一行行放到文件里面保存就可以了。下面的例子把一个print语句保存为hello.py。

print('hello '+str(2018))

这时在命令行中键入

python hello.py

就可以看到运行结果。

hello 2018

代码文件也可以直接通过双击或者命令行的方式运行。

在windows系统里面,把python代码文件保存为'.py'后缀的文件,双击文件就可以运行。

在linux系统里面,在python文件的第一行加入一句

#! /usr/bin/env python

注意,这里'#!'一定要是文件第一行开头的两个字符,并且这一行最好使用'\n'换行,而不是windows系统里面的'\r\n'。所以linux下面运行的代码文件最好在linux编辑器中编辑,在windows编辑器中编辑的代码到了linux下面可能会出现格式问题。

然后使用chmod把代码文件设置成可执行文件

chmod 777 hello.py

这样就可以直接在命令行运行。

./hello.py

9.2代码的字符串编码

代码保存到文件中也可能会引发乱码的问题。因为代码文件中经常会有中文的定义。比如说下面的语句就定义了一个中文,而且还没有使用u操作把它转化为unicode。

s='中'

它的编码到底是gbk还是utf8,还是别的编码,取决于这个代码文件是用什么编码来保存的。

要做到自动识别一个文件到底是什么编码,实际上也不难,但是会非常麻烦。放眼全球,韩文日文阿拉伯文法文德语等等各种编码不下百种,挨个尝试解析一下将会是非常耗时的事情。所以这件事python是不会去做的。

因此每个代码文件中如果含有非ascii编码的话,都需要在代码文件中声明这个代码文件是用什么编码保存的,这样python的解析器好知道代码中定义的非ascii字符的真正编码。

这个声明需要在代码文件的第一行或者第二行的位置使用。一般情况下会使用

# coding=utf-8

或者

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

来进行声明

如果第一行已经被

#!/usr/bin/env python

占用了,那么就在第二行做编码声明;如果没有,那么就在第一行做编码声明。

编码声明其实不会很严格,只要符合正则表达式

^[ \t\v]*#.*?coding[:=][\t]*([-_.a-zA-Z0-9]+)

的就可以。(正则表达式后面再讲)可以看到,有coding这个单词,有=号或者是:号,基本就会被认为是编码声明了。在写法上还是很自由的,不过还是建议少点个性化,使用最简单的就可以了。

# coding=utf-8

如果没有这个声明的话,会有什么样的效果。我们把下面这两句代码存储到文件testencode.py中,并且使用gb18030编码进行存储。

s='中'

print(repr(s))

运行的时候很快就发现了错误。

$ python testencode.py

File "testencode.py", line 1

SyntaxError: Non-ASCIIcharacter '\xd6' in file testencode.py on line 1, but no encoding declared; seehttp://python.org/dev/peps/pep-0263/ for details

解析器发现了非ascii编码的字符而且不知道从何解析。

撞了南墙后,再回头在第一行加入声明语句。修改代码为

# coding=gb18030

s='中'

print(repr(s))

此时再运行看看,代码就可以正常运行了。打印的内容是s字符串的gb18030的字符编码。

$ python testencode.py

'\xd6\xd0'

之前讲过,要把其它编码的中文字符串先使用decode转为unicode,然后再把unicode使用encode转为其它的编码,这个是最符合规矩的流程。但是偏偏有一些猴急的人,想要跳过unicode这个中介。希望直接就能从gb18030到utf8。或者从utf8直接到gb18030。或者直接就不希望在代码中出现unicode这个碍眼货。于是python只好满足了这些人的愿望,在编译器的设置中提供默认编码的设置方法。这样python的编译器就可以默默把非ascii字符按照默认编码转成unicode。unicode不是真的不见了,而是被python藏起来了而已。

这个默认编码的设置方法,就是sys模块里面的setdefaultencoding()方法。

在使用的时候,需要在代码中加三句。

import sys

reload(sys)

sys.setdefaultencoding('gb18030')

好多人都问,之前不是import了sys,为什么又要reload一次sys呢?python的语句挺简洁的,但是后面的编译机制却盘根错节,一点都不优美。这里是因为编译器在做初始化过程中,会在执行完所有的import语句后,自动加载一个叫做site模块的东西,主要用来初始化运行路径之类的,它起来了之后,setdefaultencoding方法就从sys命名空间中被删除了。这真是一件神奇的事情,其它的语言里面这种事情是闻所未闻。只怪python太灵活,所有的东西都是对象,所有对象都有命名空间,所有命名空间都可以随便修改。所以这个时候如果不reload的话,会提示sys里面没有setdefaultencoding这个方法的。

好吧,再回到刚才的问题,加入了设置默认编码的设置后,修改代码为

# coding=gb18030

import sys

reload(sys)

sys.setdefaultencoding('gb18030')

s='中'

print(type(s))

print(repr(s))

sutf8=s.encode('utf8')

print(repr(sutf8))

上面的代码并没有使用decode把s字符串转化为unicode,而是直接使用encode转化为utf8 。

再运行一下

$ python testencode.py

'\xd6\xd0'

'\xe4\xb8\xad'

可以看到,使用了默认编码之后,在代码中已经可以直接处理gb18030编码了。不需要decode成unicode了。

如果代码里面不是只处理某一种字符编码的话,不建议自行设置默认编码。上面的代码设置了gb18030为默认编码,如果碰到了utf8编码的字符串,其实还是需要乖乖decode成unicode进行处理的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180613G24SCQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券