python2 与 python3

尝试2to3工具

简单尝试2to3工具,不是很完美,如下

-import thread
+import _thread

-return [v for k, v in cls.socket_ket_map.items()]
+return [v for k, v in list(cls.socket_ket_map.items())]

-print(r.content)
+print((r.content))

3to2工具,更是不能接受,如下

b"-        socket_file = conf.get('socket')"
b"+        socket_file = conf.get(u'socket')"

b'-            print(r.content)'
b'+            print r.content'

2to3 底层是包含很多fixer,例如名为print的fixer负责处理由print语句到print函数的转换,可以启用或禁用特定的fixer(–fix–nofix)。

一个基于多个文件引用的项目,使用2to3并不能奏效。

使用six模块

six的逻辑是兼容python2.6+和python3,同样的代码可以在两种环境中执行。原理是为python2和python3变更的元素提供唯一接口。

字符串

Python3最大的变更是字符串类型为Unicode而不再是ASCII. python2可以通过from __future__ import unicode_literals导入改行为, 如果编写兼容两个环境下运行的代码, 这是很好的方案.
python2的unicode类与python3的str类是同一个类,six.text_type

比对项python2python3six
文本字符串unicode类str类six.text_type
字节字符串str类bytes类six.binary_type

python2声明的字符串是utf-8类型 type
a = ‘abc’
type(type(a)) ⇒ type

比对项python2python3
type(a)str类str类
字符串类型字节字符串文本字符串
编码utf-8unicode
type(a) == strTrueTrue
type(a) == ‘str’FalseFalse
type(a) == six.text_typeFalseTrue
python3
In [1]: import six

In [2]: six.text_type
Out[2]: str

In [3]: type('ss') == six.text_type
Out[3]: True

In [4]: type(six.text_type('哈哈'))
Out[4]: str

In [5]: type('ss')
Out[5]: str

print

python2 print可以使用()但并不支持print的参数(end,sep等), 需要使用from __future__ import print_function来完全支持python3的print

python2: print(1,2,3) ⇒ (1, 2, 3)
python3: print(1,2,3) ⇒ 1 2 3

除法

python3 int/int ⇒ float
python2 int/int ⇒ int
from __future__ import division

绝对与相对导入

python2在import foo时实际发生:

  1. 解释器尝试在标准库中导入(json\six\sys等, pandas不在标准库)
  2. 找不到尝试相对导入(在导入模块的同一个目录中寻找名称为foo.py 或者 foo/__init__.py的模块), 如果找到则完成; 如果找不到找不到尝试相对导入(在导入模块的同一个目录中寻找名称为foo.py 或者 foo/__init__.py的模块), 如果找到则完成
  3. 如果找不到, 他会开始在sys.path中的所有目录下寻找一个匹配的模块(绝对导入)

python3尽可能的移除相对导入, import foo优先局对导入,后相对导入. 强制相对导入使用 import .foo, 引入上一层目录fooimport ..foo
python2使用from __future__ import absolute_import引入python3的行为

被不推荐的类

异常

python2 raise ValueError, 'Invalid value.'raise ValueError('Invalid value.')
python3 raise ValueError('Invalid value.')

python2:

try: 
  raise ValueError('Invalid value.')
except ValueError, e:
 print('%s' % e)

python3 python2.6+

try: 
  raise ValueError('Invalid value.')
except ValueError as e:
 print('%s' % e)

python3增加了异常链

dict的方法

python2:

keysvaluesitemsreturnnote
keys()values()items()list生成内存副本
iterkeys()itervalues()iteritems()generator生成器
viewkeys()viewvalues()viewitems()生成器视图视图对象仅仅引用原始字典, 如果原始字典改变, 视图会随之改变

python3 仅保留python2的生成器视图, 并将方法名改为 keys() | values() | items()

six 模块提供的 six.viewkeys() six.viewvalues() six.viewitems()会用合适的方法法相匹配

迭代器

python2中, 迭代器期望一个无参的 next方法, 在python3中, 它变为了__next__.
如果需要一个在python2和python3中都能正确运行的迭代器, 正确的方案是

class DemoIterator(object):
  def next(self):
    return self.__next__()

任何继承DemoIterator的子类都能收到一个next方法.

six有一个six.Iterator类, 没试过.

标准库重定位

six提供了获取正确模块的唯一接口 six.moves
涉及的模块有:
python2中import StringIOfrom cStringIO import StringIO两个模块
python3中只有from io import StringIO
six中 from six.moves.cStringIO import StringIO

python2中有 picklecPickle 模块
python3中只有 pickle 模块
six中 from six.moves import cPickle as pickle

python2中有urllib urllib2 urlparse三个模块
python3中都合并到了urllib模块,
大多来自urlparse模块(读取url并将其分解为单独部分)的方法位于 urllib.parse; 很多关于解析的方法(比如quoteunquote)从urllib移到了urllib.parse
python3中urllib模块包含4个子模块:error parse request response, six.moves.urllib模块同样为4个子模块,与python3行为一致.

重命名内置函数

python版本检测

six.PY2 six.PY3 返回bool值
sys.version_info.major 返回int值2\3

还有一些包被重组, 部分没有被six收录

six支持自己增加兼容模块

 six.add_move(MovedModule('six中的名称', 'py2名称', 'py3名称'))

遇到的问题

python3调用一些数据模块默认返回utf8, 使用参数后可以返回unicode

json模块 在python3.5及以下不能自动转换utf8\utf16, python3.6+能自动转换utf8

subprocess模块universal_newlines=True参数能自动转unicode, \n换行, python2和python3兼容, python3.6增加了encode属性 python3.7增加了text属性

redis模块 redis.StrictRedis(host='127.0.0.1', port=6379, db=0, decode_responses=True) decode_responses属性会自动转

request模块的 resp.context 返回的是二进制(bytes), resp.text模块返回的是str

request模块+gzip模块+BytesIO模块+StringIO模块

import six
if six.PY3:
    def gzdecode(data):
        buf = BytesIO(data)
        gziper = gzip.GzipFile(mode='rb', fileobj=buf)
        return gziper.read()
else:
    def gzdecode(data):
        buf = StringIO(data)
        gziper = gzip.GzipFile(mode='rb', fileobj=buf)
        return gziper.read()
gzdecode(resp.context)

一个字符串转换思路 py23 :

# -*- coding: utf-8 -*-
import six
import base64
import hmac
import hashlib
import gzip

if six.PY3:
    from urllib.parse import urlencode, quote, unquote
    from urllib.request import urlopen
    from io import StringIO, BytesIO
    import _thread as thread

    def b(data):
        if isinstance(data, str):
            return data.encode('utf-8')
        return data

    def s(data):
        if isinstance(data, bytes):
            data = data.decode('utf-8')
        return data

   def u(data):
        if isinstance(data, bytes):
            data = data.decode('utf-8')
        return data

else:
    from urllib import urlencode, quote, unquote
    from urllib2 import urlopen
    from cStringIO import StringIO
    import thread

    def b(data):
        return bytes(data)

    def s(data):
        return bytes(data)
        
    def u(data):
        if isinstance(data, str):
            data = data.decode('utf-8')
        return data

注释问题, python2不报错, python3报错(python2自动做了一些转换吧)

@App.route("/win_server/run_cmd", methods=["POST"])
def win_server_run_cmd():
    """
    example:
    1. 更新并重启 ae_pr_worker/monitor_ae
    cmd=cd C:\Users\Administrator\wx_video;git pull;pm2 restart ae_pr_worker/monitor_ae
    :return:
    2. 重启shutdown -r -t 0
    :return:
    """
    cmd = request.get_json().get('cmd')
    cmds = cmd.split(';')
    ret = []
    for _cmd in cmds:
        print(_cmd)
        return_code = subprocess.call(_cmd, shell=True)
        ret.append({
            'cmd': _cmd,
            'return_code': return_code,
        })
    return jsonify(state=200, data=dict(msg='success', ret=ret))

python3报错如下:

      File "run_server.py", line 407
        """
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 109-110: truncated \UXXXXXXXX escape

python3会解析反斜杠, 改为C:/Users/Administrator/wx_video, 或者在注释前加r, r""“note”""
参考: https://blog.csdn.net/u011242657/article/details/64437612

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值