python3 读取txt替换、n_从Python2迁移到Python3实战(一) pyupgrade
前言
从这篇开始我会不定期写一些在实际工作中把项目代码从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''' # '''foo'''
在Python3中,u'foo'其实已经是字符串的'foo',默认是不会修改这个类型数据的,除非传入 --py3-plus
或者 --py36-plus
:
❯ cat unicode_literals.py
u'foo' # 'foo'
u"foo" # 'foo'
u'''foo''' # '''foo'''
❯ pyupgrade --py36-plus unicode_literals.py
Rewriting unicode_literals.py
❯ cat unicode_literals.py
'foo' # 'foo'
"foo" # 'foo'
'''foo''' # '''foo'''
Invalid escape sequences
现在flake8已经会检查出这个类型错误(W605):
# strings with only invalid sequences become raw strings
'\d' # r'\d'
# strings with mixed valid / invalid sequences get escaped
'\n\d' # '\n\\d'
# `ur` is not a valid string prefix in python3
u'\d' # u'\\d'
❯ cat escape_seq.py
'\d' # r'\d'
❯ flake8 escape_seq.py
escape_seq.py:1:2: W605 invalid escape sequence '\d'
❯ pyupgrade escape_seq.py
Rewriting escape_seq.py
❯ cat escape_seq.py
r'\d' # r'\d'
is
/ isnot
is
/ isnot
从Python3.8开始会抛出SyntaxWarning错误,应该使用 ==
/ !=
替代:
❯ python
Python 3.8.0a4+ (heads/master:289f1f80ee, May 9 2019, 07:16:38)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 is 1
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> 1 is not 1
<stdin>:1: SyntaxWarning: "is not" with a literal. Did you mean "!="?
False
>>>
pyupgrade会做如下替换:
x is 5 # x == 5
x is not 5 # x != 5
x is 'foo' # x == foo
ur
字符串文字
ur'...'
这种用法在python3已经不可用了:
ur'foo' # u'foo'
ur'\s' # u'\\s'
# unicode escapes are left alone
ur'\u2603' # u'\u2603'
ur'\U0001f643' # u'\U0001f643'
数字的L后缀
在Python2数字后面会有L后缀,在Python3不再支持了:
5L # 5
5l # 5
123456789123456789123456789L # 123456789123456789123456789
八进制数字
这个最常见的用法是修改文件权限,在Python2中可以直接使用0755,但是Python3中这样是错误的:
# Python 2
In : import os
In : !touch 1.txt
In : os.chmod('1.txt', 0755)
In : ll 1.txt
-rwxr-xr-x 1 dongwm 0 May 9 07:26 1.txt* # 755权限正常
# Python 3
In : os.chmod('1.txt', 0644)
File "", line 1
os.chmod('1.txt', 0644)
^
SyntaxError: invalid token
In : os.chmod('1.txt', 0o644)
In : ll 1.txt
-rw-r--r-- 1 dongwm 0 May 9 07:26 1.txt
pyupgrade会帮助修复这个问题:
0755 # 0o755
05 # 5
super()
class C(Base):
def f(self):
super(C, self).f() # super().f()
在Python3中,使用super不再需要手动传递self,传入 --py3-plus
或者 --py36-plus
会修复这个问题。
新式类
class C(object): pass # class C: pass
class C(B, object): pass # class C(B): pass
Python3 中只有新式类,传入 --py3-plus
或者 --py36-plus
会修复这个问题。
移除six相关兼容代码
当完全迁移到Python3之后,就没必要兼容Python2了,可以传入 --py3-plus
或者 --py36-plus
去掉six相关代码:
six.text_type # str
six.binary_type # bytes
six.class_types # (type,)
six.string_types # (str,)
six.integer_types # (int,)
six.unichr # chr
six.iterbytes # iter
six.print_(...) # print(...)
six.exec_(c, g, l) # exec(c, g, l)
six.advance_iterator(it) # next(it)
six.next(it) # next(it)
six.callable(x) # callable(x)
from six import text_type
text_type # str
@six.python_2_unicode_compatible # decorator is removed
class C:
def __str__(self):
return u'C()'
class C(six.Iterator): pass # class C: pass
class C(six.with_metaclass(M, B)): pass # class C(B, metaclass=M): pass
isinstance(..., six.class_types) # isinstance(..., type)
issubclass(..., six.integer_types) # issubclass(..., int)
isinstance(..., six.string_types) # isinstance(..., str)
six.b('...') # b'...'
six.u('...') # '...'
six.byte2int(bs) # bs[0]
six.indexbytes(bs, i) # bs[i]
six.iteritems(dct) # dct.items()
six.iterkeys(dct) # dct.keys()
six.itervalues(dct) # dct.values()
six.viewitems(dct) # dct.items()
six.viewkeys(dct) # dct.keys()
six.viewvalues(dct) # dct.values()
six.create_unbound_method(fn, cls) # fn
six.get_unbound_method(meth) # meth
six.get_method_function(meth) # meth.__func__
six.get_method_self(meth) # meth.__self__
six.get_function_closure(fn) # fn.__closure__
six.get_function_code(fn) # fn.__code__
six.get_function_defaults(fn) # fn.__defaults__
six.get_function_globals(fn) # fn.__globals__
six.assertCountEqual(self, a1, a2) # self.assertCountEqual(a1, a2)
six.assertRaisesRegex(self, e, r, fn) # self.assertRaisesRegex(e, r, fn)
six.assertRegex(self, s, r) # self.assertRegex(s, r)
目前还有 six.add_metaclass
这个点没有实现,其他的都可以了~
f-strings
这是我最喜欢的一个功能,现在迁移到Python3都会迁到Python3.6+,所以可以直接使用 --py36-plus
参数,字符串格式化不需要用str.format,而是直接用f-strings:
'{foo} {bar}'.format(foo=foo, bar=bar) # f'{foo} {bar}'
'{} {}'.format(foo, bar) # f'{foo} {bar}'
'{} {}'.format(foo.bar, baz.womp} # f'{foo.bar} {baz.womp}'
后记
项目地址: https://github.com/asottile/pyupgrade
我已经在酱厂最大的几个项目之一应用了pyupgrade,已经达到生产环境使用的标准,请放心使用~
python3 读取txt替换、n_从Python2迁移到Python3实战(一) pyupgrade相关推荐
- Python3读取txt数据
从txt文件中导入数据 1.操作步骤 2.代码实现 3.函数说明 1.操作步骤 (1)打开文件读取整个文件 函数open返回一个表示文件的对象,对象存储在infile中.关键字with在不需要访问文件 ...
- python3读取txt文件数字签名_hash文件-对文件进行数字签名
(一)windows自带hash命令: certutil -hashfile D:\1.exe MD5 # md5的hash值为32位 certutil -hashfile ...
- Python3读txt,UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xd0 in position 0: invalid continu
问题: Python3读取txt文件时 报错UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 0: invali ...
- 快乐的迁移到 Python3
为数据科学家提供的 Python3 特性简述 在机器学习和其他需大批量操作数据的科学领域,Python 已经成为了一门主流语言.它拥有各种深度学习框架和一系列完善的数据处理和可视化工具. 然而,Pyt ...
- python读取txt文件写入-Python读写txt文本文件的操作方法全解析
一.文件的打开和创建 >>> f = open('/tmp/test.txt') >>> f.read() 'hello python! hello world! ...
- python2好还是python3好-新手入门选择Python2还是Python3
1. 前言 Python的发展很快,几乎每年都在版本迭代.目前Python有两个主要版本,一个是python2.x,另一个是python3.x. 兔子先生最早接触Python的时候,使用的是pytho ...
- python3读取excel数据-python3读取Excel表格数据的代码分享
python3 读取Excel表格中的数据 需要先安装openpyxl库 通过pip命令安装: pip install openpyxl 源码如下: #!/usr/bin/python3 #-*- c ...
- Matlab读取txt文件中的数据(使用textread函数)
在使用Matlab处理数据时,我们经常需要读取txt文档,可以使用Matlab中强大的textread函数. 它的基本语法是: [A,B,C,...] = textread(filename,form ...
- python读取文件如何去除空格_python读取txt文件时怎么去掉空格
python属于什么型语言 python通过什么实现映射 Python读取TXT文件可以通过replace()函数来去除TXT文件中的空格,基本结构:replace(to_replace, value ...
最新文章
- __new__ __init__区别
- 图片的批量下载 和 爬虫爬取图片数据集
- POJ2263 ZOJ 1952
- boost::hana::index_if用法的测试程序
- SpringMVC源码解析与思考
- LeetCode() Word Search II
- php对表格的处理,JavaScript_js处理表格对table进行修饰,js处理表格 1、行颜色间隔显示 - phpStudy...
- JAVA之旅(五)——this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块...
- 374. Guess Number Higher or Lower
- 敏捷开发生态系统系列之二:敏捷生态系统-计划跟踪 I(跨职能团队-共同估算-每日立会-同行压力)...
- 树莓派modelB无法识别exFat格式的SD卡
- 2019APMCM亚太数学建模题目
- “十四五”融合地表水国控断面监测数据(约3641个点位,含水质等级、水温,pH,溶解氧,电导率,浊度,高猛酸盐指数,化学需氧量,五日生化需氧量,氨氮,总磷,总氮,铜,锌,氟化物,硒,砷,汞,镉,等)
- 无源晶振负载电容值CL匹配方法及说明
- 综合使用公网/专网等频段!今日,工信部发布工业互联网和物联网无线电频率使用指南(附下载)...
- 220927工作日志
- C/C++ error/exception throw: access violation reading location 0x....;
- LINUX-查看历史操作记录
- JAVA大数据的第五十九天——The authenticity of host ‘gree129 (192.168.**.129)‘ can‘t be established.
- 学习数据分析、数据挖掘、大数据ETL工程师到什么程度可以找工作?