前言
从这篇开始我会不定期写一些在实际工作中把项目代码从Python2.7迁移到最新的Python 3.7的经验。
这篇先介绍pyupgrade - 一个修改代码中Python 2语法到最新版本写法的工具,同时它还可以作为pre-commit钩子,可以在代码提交或者push时拒绝引入旧的用法。
为什么需要这么一个工具呢?3个理由:
替换代码中旧版本Python的用法。例如
'%s %s'%(a,b)
这种百分号的字符串格式化写法替换成Python 3的新语法。例如在Python 3中
super
不再需要传递self、字符串格式化在Python 3.6及以后可以直接用f-strings迁移后不再需要支持Python2,所以应该去掉six模块的相关使用,直接用Python3的代码写才是正途。
我日常维护的项目中Python代码都在几千到上百万行级别,可以设想一下,如果人工来做代码替换将是一个极为浩大的工程。
在现有的Python世界,过去只有lib2to3模块和其衍生品(之后我会专门讲),但是效果有限,pyupgrade是一个很好的补充,我们来了解一下它都实现了那些功能
集合
set(()) # set()
set([]) # set()
set((1,)) # {1}
set((1, 2)) # {1, 2}
set([1, 2]) # {1, 2}
set(x for x in y) # {x for x in y}
set([x for x in y]) # {x for x in y}
左面是替换前的代码,后面井号后的注释部分是替换后的效果。set相关的部分算是统一用法,并不是左面的写法在Python3已经不可用。
字典解析
dict((a, b) for a, b in y) # {a: b for a, b in y}
dict([(a, b) for a, b in y]) # {a: b for a, b in y}
同上,属于统一用法
Python2.7+ Format说明符
'{0} {1}'.format(1, 2) # '{} {}'.format(1, 2)
'{0}' '{1}'.format(1, 2) # '{}' '{}'.format(1, 2)
从Python2.7开始,不再强制指定索引
使用str.format替代printf风格的字符串format写法
'%s %s' % (a, b) # '{} {}'.format(a, b)
'%r %2f' % (a, b) # '{!r} {:2f}'.format(a, b)
'%(a)s %(b)s' % {
'a': 1, 'b': 2} # '{a} {b}'.format(a=1, b=2)
后面的是Python2.7推荐的写法。但是可以传入 --keep-percent-format
忽略这类修改。
Unicode literals
u'foo' # 'foo'
u"foo" # 'foo'
u'''foo'