查看下当前python版本, 如果已经是Python 3,则跳过
python --version
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install python
安装完成后查看下新python版本和位置 ,发现python3会成本默认版本。我的是/usr/local/opt/python/libexec/bin/python
which python
pip3 install --upgrade pip setuptools wheel
If you need Homebrew's Python 2.7 run
brew install python@2
Pip, setuptools, and wheel have been installed. To update them run
pip3 install --upgrade pip setuptools wheel
You can install Python packages with
pip3 install <package>
They will install into the site-package directory
/usr/local/lib/python3.6/site-packages
之后python的2/3使用都可以自由切换
virtualenv venv //python3
virtualenv venv -p python2.7 //python2
python3内置2to3命令, 简单的代码可以直接转3
2to3 -w gmc.py 生成转换的bake文件
2to3 -w gmc.py 直接覆盖原文件
2to3 --help
Options:
-h, --help show this help message and exit
-d, --doctests_only Fix up doctests only
-f FIX, --fix=FIX Each FIX specifies a transformation; default: all
-j PROCESSES, --processes=PROCESSES
Run 2to3 concurrently
-x NOFIX, --nofix=NOFIX
Prevent a transformation from being run
-l, --list-fixes List available transformations
-p, --print-function Modify the grammar so that print() is a function
-v, --verbose More verbose logging
--no-diffs Don't show diffs of the refactoring
-w, --write Write back modified files
-n, --nobackups Don't write backups for modified files
-o OUTPUT_DIR, --output-dir=OUTPUT_DIR
Put output files in this directory instead of
overwriting the input files. Requires -n.
-W, --write-unchanged-files
Also write files even if no changes were required
(useful with --output-dir); implies -w.
--add-suffix=ADD_SUFFIX
Append this string to all output filenames. Requires
-n if non-empty. ex: --add-suffix='3' will generate
.py3 files.
python2 | python3 | 备注 |
---|---|---|
print() | 输出一个空白行,python3需要调用不带参数的print() | |
print 1, 2, | print(1,2, end=' ') | python2中如果使用一个,作为print结尾,将会用空格分割输出的结果,然后在输出一个尾随的空格,而不输回车。python3里,把end=' ' 作为一个关键字传给print()可以实现同样的效果,end默认值为'\n',所以通过重新指定end参数的值,可以取消在末尾输出回车符号 |
print >> sys.stderr, 1, 2, 3 | print(1, 2, 3, file=sys.stderr | python2中,可以通过>>pipe_name语法,把输出重定向到一个管道,比如sys.stderr.在python3里,可以通过将管道作为关键字参数file的值传递给print()完成同样的功能。 |
python2中有两种字符串类型:Unicode字符串和非Unicode字符串 Python3中只有一种类型:Unicode字符串
python2 | python3 | 备注 |
---|---|---|
u'PapayaWhip' | 'PapayaWhip' | python2中的Unicode字符串在python3即为普通字符串 |
ur'PapayaWhip\foo' | r'PapayWhip\foo' | Unicode原始字符串(使用这种字符串,python不会自动转义反斜线"")也被替换为普通的字符串,因为在python3里,所有原始字符串都是以unicode编码的。 |
python2 | python3 | 备注 |
---|---|---|
unicode()把对象转换成unicode字符串 str()把对象转换为非Unicode字符串 |
unicode字符串,所以str()函数即可完成所有的功能 |
python2 | python3 | 备注 |
---|---|---|
<> or != | != | |
[1, 2] > ‘foo’ = False (1, 2) > ‘foo’ = True [1, 2] > (1, 2) = False |
TypeError: unorderable types: list() > str() | Python 3 中当对不可排序类型做比较的时候,会抛出一个类型错误 |
python2里,许多字典类方法的返回值是列表。最常用方法有keys, items和values python3,所有以上方法的返回值改为动态试图。在一些上下文环境里,这种改变不会产生影响。如果这些方法的返回值被立即传递给另外一个函数,而且那个函数会遍历整个序列,那么以上方法的返回值是列表或视图并不会产生什么不同。如果你期望获得一个被独立寻址元素的列表,那么python3的这些改变将会使你的代码卡住,因为视图不支持索引
python2 | python3 | 备注 |
---|---|---|
a_dictionary.keys() | list(a_dictionary.keys()) | 使用list()将keys 返回值转换为一个静态列表 |
a_dictionary.items() | list(a_dictionary.items()) | 将items返回值转为列表 |
a_dictionary.iterkeys() | iter(a_dictionary.keys()) | python3不再支持iterkeys,使用iter()将keys()的返回值转换为一个迭代器 |
[i for i in a_dictionary.iterkeys()] | [ i for i in a_dictonary.keys()] | 不需要使用额外的iter(),keys()方法返回的是可迭代的 |
min(a_dictionary.keys()) | no change | 对min(),max(),sum(),list(),tuple(),set(),sorted(),any()和all()同样有效 |
重命名或重新组织的模块: |
python2里,filter()方法返回一个列表,这个列表是通过一个返回值为True或False的函数来检测序列里的每一项的值
python3中,filter()函数返回一个迭代器,不再是列表
跟filter()的改变一样,map()函数现在返回一个迭代器,python2中返回一个列表
在python3里,reduce()函数已经从全局名字空间移除,现在被放置在fucntools模块里
python2 | python3 | 备注 |
---|---|---|
filter(a_function, a_sequence) | list(filter(a_function, a_sequence)) | |
map(a_function,'PapayaWhip' | list(map(a_function, 'PapayaWhip')) | |
reduce(a,b,c) | from functools import reduce reduce(a, b, c) |
python2 | python3 | 备注 |
---|---|---|
except (RuntimeError, ImportError), e pass | except(RuntimeError, ImportError) as e | |
ex.message | 没有message属性 | |
支持raise MyException, 'error message' | 只支持 raise MyException('error message') |
python2里,有两种方法获得一定范围内的数字:range(),返回一个列表,还有xrange(),返回一个迭代器
python3 里,range()返回迭代器,xrange()不再存在
python2 | python3 | 备注 |
---|---|---|
a_list = range(10) | a_list= list(ange(10)) |
python2有两个全局函数,用在命令行请求用户输入。 第一个叫input(),它等待用户输入一个python表达式(然后返回结果)。用户输入什么他就返回什么, 第二个叫做raw_input(),输入结果为字符串形式 python3 通过input替代了他们,输入结果为字符串形式
python2 | python3 | 备注 |
---|---|---|
raw_input() | input |
python2,函数的代码可用访问到函数本身的特殊属性
python3为了一致性,这些特殊属性被重命名了
python2 | python3 | 备注 |
---|---|---|
a_function.func_name | a_function.name | __name__属性包含了函数的名字 |
a_function.func_doc | a_function.doc | __doc__包含了函数源代码定义的文档字符串 |
a_function.func_defaults | a_function.defaults | 是一个保存参数默认值的元组 |
a_function.func_dict | a_function.dict | __dict__属性是一个支持任意函数属性的名字空间 |
a_function.func_closure | a_function.closure | __closure__属性是由cell对象组成的元组,包含了函数对自由变量的绑定 |
a_function.func_globals | a_function.globals | 是对模块全局名字空间的引用 |
a_function.func_code | a_function.code | 是一个代码对象,表示编译后的函数体 |
python2中,文件对象有一个xreadlines()方法,返回一个迭代器,一次读取文件的一行。这在for循环中尤其实用
python3中,xreadlines()方法不再可用
python2 | python3 | 备注 |
---|---|---|
lambda (x,): x + f(x) | lambda x1 : x1[0] + f(x1[0]) | 注1 |
lambda (x,y): x + f(y) | lambda x_y : x_y[0] + f(x_y[1]) | 注2 |
lambda (x,(y,z)): x + y + z | lambda x_y_z: x_y_z[0] + x_y_z[1][0]+ x_y_z[1][1] | 注3 |
lambda x,y,z: x+y+z | unchanged | 注4 |
注1:如果定义了一个lambda函数,使用包含一个元素的元组作为参数,python3中,会被转换成一个包含到x1[0]的引用的lambda函数。x1是2to3脚本基于原来元组里的命名参数自动生成的。
注2:使用含有两个元素的元组(x,y)作为参数的lambda函数被转换为x_y,它有两个位置参数,即x_y[0]和x_y[1]
注3:2to3脚本可以处理使用嵌套命名参数的元组作为参数的lambda函数。产生的结果有点晦涩,但python3下和python2的效果是一样的。
注4:可以定义使用多个参数的lambda函数。语法在python3同样有效
python2,zip()可以使用任意多个序列作为参数,它返回一个由元组构成的列表。第一个元组包含了每个序列的第一个元素,第二个元组包含了每个序列的第二个元素,依次递推
python3中返回一个迭代器,而非列表
python2 | python3 | 备注 |
---|---|---|
zip(a,b,c) | list(zip(a,b,c) | python3中可以通过list函数遍历zip()返回的迭代器,形成列表返回 |
d.join(zip(a,b,c)) | no change | 在已经会遍历所有元素的上下文环境里,zip()本身返回的迭代器能够正常工作,2to3脚本检测到后,不再修改 |
python2 | python3 | 备注 |
---|---|---|
types.UnicodeType | str | |
types.StringType | bytes | |
types.DictType | dict | |
types.IntType | int | |
types.LongType | int | |
types.ListType | list | |
types.NoneType | type(None) | |
types.BooleanType | bool | |
types.BufferType | memoryview | |
types.ClassType | type | |
types.ComplexType | complex | |
types.EllipsisType | type(Ellipsis) | |
types.FloatType | float | |
types.ObjectType | object | |
types.NotImplementedType | type(NotImplemented) | |
types.SliceType | slice | |
types.TupleType | tuple | |
types.TypeType | type | |
types.XRangeType | range |
python2,如果需要编写一个遍历元组的列表解析,不需要在元组值周围加上括号
python3里,这些括号是必需的
python2 | python3 | 备注 |
---|---|---|
[ i for i in 1, 2]' | '[i for i in (1,2)] |
python2里,可以通过在类的声明中定义metaclass参数,或者定义一个特殊的类级别(class-level__metaclass__属性,来创建元类
python3中,__metaclass__属性被取消了
python2 | python3 | 备注 |
---|---|---|
class C(metaclass=PapayaMeta): pass | unchanged | |
class Whip: metaclass = PapayMeta | class Whip(metaclass=PapayaMeta): pass | |
class C(Whipper, Beater): metaclass = PapayaMeta | class C(Whipper, Beater, metaclass=PapayMeta): pass |
all_feature_names = [
"nested_scopes",
"generators",
"division",
"absolute_import",
"with_statement",
"print_function",
"unicode_literals",
"barry_as_FLUFL",
"generator_stop",
"annotations",
]
module | python2 | python3 | 备注 |
---|---|---|---|
from future import absolute_import | import string先当前目录,再系统中查找string | 先在系统中查找, 再在当前查找 | |
from future import division | 3 / 4 = 0 | 3 / 4 = 0.75; 3//4 = 0 | |
from future import print_function | 不支持print a | print(a) | |
from future import unicode_literals | print ''xxx' is unicode?', isinstance('xxx', unicode) >> False | print ''xxx' is unicode?', isinstance('xxx', unicode) >> True |
如果你正在移植代码,这个变化是特别危险的。或者你在 Python 2 上执行 Python 3 的代码。因为这个整除的变化表现在它会被忽视(即它不会抛出语法异常)。 因此,我还是倾向于使用一个 float(3)/2 或 3/2.0 代替在我的 Python 3 脚本保存在 Python 2 中的 3/2 的一些麻烦(并且反而过来也一样,我建议在你的 Python 2 脚本中使用 from future import division)
module | python2 | python3 | 备注 |
---|---|---|---|
3 / 2 | 1 | 1.5 | |
3 // 2 | 1 | 1 | |
3 / 2.0 | 1.5 | 1.5 | |
3 // 2.0 | 1.0 | 1.0 |
my_generator = (letter for letter in 'abcdefg')
python2 | python3 | 备注 |
---|---|---|
next(my_generator) my_generator.next() |
next(my_generator) | Python 3 移除了方法.next() |
好消息:在 Python 3.x 中 for 循环变量不会再导致命名空间泄漏。 在 Python 3.x 中做了一个改变,在 What’s New In Python 3.0 中有如下描述: “列表推导不再支持 [... for var in item1, item2, ...] 这样的语法。使用 [... for var in (item1, item2, ...)] 代替。也需要提醒的是列表推导有不同的语义: 他们关闭了在 list() 构造器中的生成器表达式的语法糖, 并且特别是循环控制变量不再泄漏进周围的作用范围域.”
i = 1
print 'before: i =', i
print 'comprehension: ', [i for i in range(5)]
print 'after: i =', i
python2 | python3 | 备注 |
---|---|---|
before: i = 1 comprehension: [0, 1, 2, 3, 4] after: i = 4 |
before: i = 1 comprehension: [0, 1, 2, 3, 4] after: i = 1 |
python2 | python3 | 备注 |
---|
python2 | python3 | 备注 |
---|---|---|
pip install pylint | pip install pylint --upgrade | pylint |
Pylint can be simply installed by running:
pip install pylint
If you are using Python 3.6+, upgrade to get full support for your version:
pip install pylint --upgrade