跳转到: 导航, 搜索

Python3

此页面跟踪 OpenStack Python 3 移植工作的进展情况。

IRC: #openstack-dev

加入 Freenode 网络的 #openstack-dev IRC 频道讨论 Python 3。

当前状态

自 Ussuri 以来,OpenStack 除 Swift 和 Storlets 之外均为 Python3。所有其他项目的 Python2.7 支持和测试已被移除。有关更多详细信息,请参阅 Drop py2.7 社区目标

发布 Python 版本 笔记
V python3.6 python3.7 python3.8 [1]
Ussuri (放弃 Python 2.7) python3.6 python3.7 [2] 在 Ussuri 中,OpenStack 除 Swift 和 Storlets 之外均为 python3-only。请参阅 放弃 Python 2.7 目标
Train python2.7 python3.6 python3.7 [3] Train 是需要 python2.7 测试的最后一个版本。

Python 3

为什么现在 OpenStack 要迁移到 Python 3?

Python 3 通常被认为是新的 Python 版本,它破坏了兼容性并引发了新的 Unicode 问题。Python 3 不仅仅是这样。它是一种新的、干净的语言,具有更一致的语法。它具有许多新功能,多达 15 个新模块。Python 3 已经得到主要 Linux 发行版的良好支持,而 Python 2.7 已经达到其生命周期结束。慢慢地,一些错误无法在 Python 2.7 中修复,只能在最新的 Python 3 版本中修复。Python 3 已经发布 5 年了,被认为是一种成熟的编程语言。


OpenStack 项目的 Python 3 状态

通用库 (Oslo 项目)

请参阅 programs.yaml 以获取通用库的列表。

项目 仅支持 Python 3 (Ussuri 及以后) Python 3 兼容性 备注
automaton Yes Yes
castellan Yes Yes
cliff Yes Yes
debtcollector Yes Yes
futurist Yes Yes
oslo.cache Yes Yes
oslo.concurrency Yes Yes
oslo.config Yes Yes
oslo.context Yes Yes
oslo.db Yes Yes
oslo.i18n Yes Yes
oslo.log Yes Yes
oslo.messaging Yes Yes
oslo.middleware Yes Yes
oslo.policy Yes Yes
oslo.privsep Yes Yes
oslo.reports Yes Yes
oslo.rootwrap Yes Yes
oslo.serialization Yes Yes
oslo.service Yes Yes
oslotest Yes Yes
oslo.versionedobjects Yes Yes
oslo.vmware Yes Yes
oslo.utils Yes Yes
pylockfile 不适用 Yes 项目已弃用。
stevedore Yes Yes
taskflow Yes Yes
tooz Yes Yes

开发工具

项目 仅支持 Python 3 (Ussuri 及以后) Python 3 兼容性 备注
cookiecutter Yes
hacking Yes
pbr pbr 没有上限,因此我们需要继续支持 py2.7 代码以确保安全。
stackforge/python-jenkins
openstack-infra/jenkins-job-builder 部分 https://review.openstack.org/172238

OpenStack 客户端

项目 仅支持 Python 3 (Ussuri 及以后) Python 3 兼容性 CI 测试正在运行? Python 3 分类器? 被以下问题阻塞 备注
keystonemiddleware Yes Yes 投票 在 PyPI 上
python-barbicanclient Yes 投票 在 PyPI 上 https://review.opendev.org/#/c/699096/
python-ceilometerclient Yes Yes 投票 在 PyPI 上
python-cinderclient Yes Yes 投票 在 PyPI 上
python-fuelclient 不适用 Yes voting 在 PyPI 上 该项目不再维护。
python-glanceclient Yes Yes 投票 在 PyPI 上
python-heatclient Yes Yes 投票 在 PyPI 上
python-ironicclient Yes Yes 投票 在 PyPI 上
python-keystoneclient Yes Yes 投票 在 PyPI 上
python-manilaclient Yes Yes 投票 在 PyPI 上
python-zaqarclient Yes Yes 投票 在 PyPI 上
python-masakariiclient Yes Yes 投票 在 PyPI 上
python-monascaclient Yes Yes 投票 在 PyPI 上
python-novaclient Yes Yes 投票 在 PyPI 上
python-neutronclient Yes Yes 投票 在 PyPI 上
python-octaviaclient Yes Yes 投票 在 PyPI 上
python-openstackclient Yes Yes 投票 在 PyPI 上 截至 0.9
python-saharaclient Yes Yes 投票 在 PyPI 上
python-searchlightclient Yes Yes 投票 在 PyPI 上
python-senlinclient Yes Yes 投票 在 PyPI 上
python-swiftclient Yes 投票 在 PyPI 上 Swift 将继续支持 python2。
python-tuskarclient 不适用 Yes 投票 在 PyPI 上 该项目不再维护。
python-troveclient Yes Yes 投票 在 PyPI 上
python-watcherclient Yes Yes 投票 在 PyPI 上
python-designateclient Yes Yes 投票 在 PyPI 上

OpenStack 库

项目 仅支持 Python 3 (Ussuri 及以后) Python 3 兼容性 CI 测试正在运行? Python 3 分类器? 备注
blazar-nova Yes Yes voting Yes
ceilometermiddleware Yes Yes voting Yes
django_openstack_auth 不适用 Yes voting Yes

代码已合并到 openstack/horizon 中。

glance_store Yes Yes voting Yes
heat-translator Yes Yes voting Yes
ironic-lib Yes Yes voting Yes
keystoneauth Yes Yes voting Yes
keystonemiddleware Yes Yes voting Yes
ldappool Yes Yes voting Yes
monasca-statsd Yes Yes voting Yes
mistral-lib Yes Yes voting Yes
neutron-lib Yes Yes voting Yes
octavia-lib Yes Yes voting Yes
os-brick Yes Yes voting Yes
os-client-config Yes Yes voting Yes
os-traits Yes Yes voting Yes
os-vif Yes Yes voting Yes
os-win Yes Yes voting Yes
osc-lib Yes Yes voting Yes
osc-placement Yes Yes voting Yes
pycadf Yes Yes voting Yes
shade Yes voting Yes shade 处于扩展维护状态。
sqlalchemy-migrate 不适用 Yes voting Yes 该项目不在 OpenStack 的维护范围内
sushy Yes Yes voting Yes
taskflow Yes Yes voting Yes
tosca-parser Yes Yes voting Yes

依赖项:环境标记

示例:不为 Python 3.3 及更高版本安装“futures”依赖项

futures; python_version < '3.2'

OpenStack 应用程序 (tc:approved-release)

OpenStack 应用程序 经 OpenStack 技术委员会批准

项目 仅支持 Python 3 (Ussuri 及以后) 单元测试通过 Python 3 py35 gate 功能测试 评论
ceilometer Yes Yes voting
cinder Yes Yes voting integrated-gate-py35

cinder-python3 蓝图(由 Victor Stinner 编写)已接受用于 Liberty。补丁:bp/cinder-python3 主题。注意:提交消息必须使用“Partial-Implements: blueprint cinder-python3”才能链接到蓝图。Kendall Nelson、Ivan Kolodyazhny (核心) 和 Eric Harney (核心) 偏好这种语法:请参阅 COMMIT_MSG

designate Yes Yes voting designate-bind9-py36 designate-bind9-py35 依赖于 oslo.service WSGI 代码,该代码在使用 SSL 的情况下无法在 Python 3 下工作。功能 tempest 测试在这两个作业上运行。[4]
glance Yes Yes voting integrated-gate-py35 依赖于 oslo.service WSGI 代码,该代码无法在 Python 3 下工作。[5]

Victor Stinner 正在将 Glance 移植到 Python3。补丁:Glance (主题: py3) 的补丁

heat Yes Yes voting heat-functional-convg-mysql-lbaasv2-py35

Sirushti Murugesan 编写并实施了规范 Python34 支持(已接受用于 Liberty)。Mitaka 版本将完全支持 Python 3。Sirushti Murugesan 完成了几乎所有的工作!

horizon Yes Yes voting horizon-openstack-tox-python3-django111,horizon-integration-tests, horizon-dsvm-tempest-plugin

George Peristerakis 编写了 使 Horizon python3.4 兼容 于 2015 年 5 月,该蓝图已获得批准。补丁:bp/porting-python3 主题

ironic Yes Yes voting ironic-tempest-dsvm-ipa-partition-pxe_ipmitool-tinyipa-python3

Python 3.4 单元测试现在正在 openstack/ironic 上运行。单元测试是一个投票作业。 感谢 Victor Sergeyev 完成所有工作,更新 Ironic 代码以使其通过使用 Python 3.4 的单元测试:在 py34 环境中运行测试

keystone Yes Yes voting integrated-gate-py35

转向 pyldap 和新的 ldappool 是 Newton 中解决的主要障碍。感谢 Keystone 团队在 Newton 中完成所有工作。

neutron Yes Yes voting integrated-gate-py35

移植到 Python 3 规范(由 Cyril Roelandt 编写)已接受用于 Liberty,移植正在进行中。蓝图 neutron-python3 的补丁

neutron-lbaas 不适用 Yes voting neutron-lbaasv2-dsvm-py3x-api 和 neutron-lbaasv2-dsvm-py3x-api-namespace 该项目不再维护。
neutron-fwaas Yes Yes voting neutron-fwaas-networking-midonet-cross-py35 (非投票)
neutron-vpnaas Yes Yes voting
nova Yes Yes voting integrated-gate-py35

2019-01-24 状态:单元测试全部运行并通过 Python 3 投票,通过使用 mox3 包。只有 3 个单元测试文件仍在 mox3 中(nova/tests/unit/cells/test_cells_messaging.py、nova/|tests/unit/network/test_neutronv2.py、nova/tests/unit/network/test_manager.py)。

我们建议贡献者不要花时间替换正在测试 cells v1 和 nova-network(test_cells_messaging.py 和 test_manager.py)的文件中的 mox,因为两者都计划尽快删除。进度跟踪:https://blueprints.launchpad.net/nova/+spec/mox-removal-stein

sahara Yes Yes voting sahara-tests-scenario-py3 (实验) 2018-02-23 状态:作业在 devstack 部署期间失败,因为 swift 未启动。其依赖项列表很小,像 keystone 这样的组件是可选的。这通过一个额外的依赖项部分解决了:https://review.openstack.org/#/c/544121/ 但这需要 a) devstack 中的支持(https://review.openstack.org/#/c/544383/ 中的临时支持) b) 至少另一个额外的依赖项,或者一种更通用的方法;即使在 devstack 中明确要求额外的依赖项,从 pip 安装的额外依赖项也会破坏依赖补丁的测试。

我们面临 pickle 库和 python 3 的问题,一旦解决,我们就可以尝试使 python 3 gate 投票。

swift Yes voting Swift 将继续支持 python2。

更新 (2016-06-27):master 分支目前处于软冻结状态,以便合并加密中间件

Python 3 错误:https://bugs.launchpad.net/swift/+bug/1614289

计划向 Swift 添加 Python 3 支持。补丁:带有主题 py3 的补丁

Python 3 单元测试需要 liberasurecode >= 1.0.9 和 PyEClib >= 1.0.9。要在 /usr 中安装 liberasurecode

git clone https://bitbucket.org/tsg-/liberasurecode/
cd liberasurecode
/autogen.sh  && /configure --prefix=/usr && make && sudo make install

liberasurecode >= 1.0.9 在 Ubuntu Precise、Ubuntu Trusty、Fedora 22、Fedora 23 和 CentoOS 7 中可用。

更新 2018-02-22:当前阻止器的列表:https://gist.github.com/tipabu/833b03a865dba96e9fa2230b82f5d075

更新 2018-03-06:当前阻止器的列表,附带进度说明:https://etherpad.openstack.org/p/Swift_py3

trove Yes Yes voting trove-devstack-base

2019-01-06 状态:单元测试 - 1708 个测试,1707 个通过,1 个跳过。

集成测试基于 trove-devstack-base 作业。

2016-07-25 状态:1,155 / 2,014 (run_tests.py: 398; testr: 1,521; generate_examples: 95) 单元测试 (57%),TODO:859 个测试

2016-06-22 状态:839 (testtools) / 1,992 (run_tests.py: 398; testr: 1,499; generate_examples: 95) 单元测试 (42%),TODO:1,153 个测试

2018-02-22 状态:现在只有一个测试在黑名单中:guestagent.test_operating_system

run_tests.py (proboscis) 失败:https://review.openstack.org/#/c/346905/1

Victor Stinner 提出了 trove-python3 蓝图 用于 Mitaka。

来自 Victor (2016/3/17):"我建议在峰会之前讨论 Python 3。例如,准备一个将 Trove 移植到 Python 3 的具体计划,列出技术问题,如 MySQL-Python 等。"

补丁:搜索 bp/trove-python3 主题

其他 OpenStack 应用程序和项目

OpenStack 所有项目的列表:projects.yaml

项目 仅支持 Python 3 (Ussuri 及以后) 单元测试通过 Python 3 py35 gate 功能测试 评论
adjutant Yes Yes voting 部分* (*) Adjutant 的单元测试包括针对 Adjutant API 使用 DRF 内部测试类的一套 API 测试。虽然不是真正的功能测试,但它们会启动一个内部 Web 服务器并处理来自 Adjutant 的真实工作负载,对我们接触到的外部 API 和服务(Keystone、Nova、Neutron 等)进行模拟。 这测试了 92% 的代码,因此很可能涵盖了大多数 py3 与 py2 的问题。 Tempest 测试也计划在以后进行。
aodh Yes Yes voting
barbican Yes Yes voting 未指定

蓝图 barbican-py3

blazar Yes Yes voting blazar-devstack-dsvm-py35
cloudkitty Yes Yes voting cloudkitty-tempest-full-python3
congress Yes Yes 投票* congress-devstack-py35-api-mysql

(*) py35 支持需要对 antlr3 包进行微小修改,从而导致 Debian 打包困难

Random Stacker 编写了一个 support-python3 蓝图。补丁:搜索主题 bp/support-python3

cyborg Yes 没有作业 没有作业
designate Yes Yes voting designate-devstack-pdns4-py35(仅检查队列)

Pradeep Kumar Singh 提出了 blueprint designate-py3,该蓝图已被 Liberty 接受。补丁:主题:bp/designate-py3

ec2-api Yes Yes voting openstack-tox-py35
freezer Yes Yes voting
karbor Yes Yes voting
kuryr Yes Yes voting openstack-tox-py35
magnum Yes Yes voting (投票:magnum-functional-api) 且 (非投票:magnum-functional-k8s 且 magnum-functional-swarm-mode)
manila Yes Yes voting manila-tempest-minimal-dsvm-dummy
manila-ui Yes Yes voting horizon-openstack-tox-python3-django111
masakari Yes Yes voting openstack-tox-py35
mistral Yes Yes voting
monasca-agent Yes Yes voting monasca-tempest-python3-influxdb https://storyboard.openstack.org/#!/story/2000975
monasca-api Yes Yes voting monasca-tempest-python3-influxdb https://storyboard.openstack.org/#!/story/2000975
monasca-log-api Yes Yes voting monascalog-python3-tempest
monasca-ui Yes Yes voting https://storyboard.openstack.org/#!/story/2000975
murano Yes Yes voting

蓝图:murano-python-3-support

murano-agent Yes Yes voting

蓝图:murano-python-3-support

octavia Yes Yes voting octavia-tox-functional-py35
panko Yes Yes voting panko-tox-py35-mysql 和 panko-tox-py35-postgresql
qinling Yes Yes voting
rally Yes Yes voting rally-tox-functional-py3 和 rally-tox-self

非常感谢 Andrey Kurilin 为此方向所做的许多工作

searchlight Yes Yes voting openstack-tox-py36
senlin Yes Yes voting senlin-dsvm-tempest-py35-api、senlin-dsvm-tempest-py35-functional、senlin-dsvm-tempest-py35-integration(仅检查,非投票)
solum Yes Yes voting solum-devstack-py35(仅检查)

Victor Stinner 提出了 blueprint solum-python3,该蓝图已被批准。补丁:搜索 bp/solum-python3 主题(开放的评审)。

storlets Yes voting Storlets 将保留 python2 支持。
tacker Yes Yes voting tacker-functional-devstack-python3(仅检查,非投票)
tricircle Yes Yes voting
vitrage Yes Yes voting vitrage-dsvm-api-py35 和 vitrage-dsvm-datasources-py35
watcher Yes Yes voting
zaqar Yes Yes voting
zun Yes Yes voting zun-tempest-py35-docker-sql
networking-l2gw Yes Yes voting
vmware-nsx Yes Yes voting 所有第三方 CI 作业都在运行 python 3
vmware-nsxlib Yes Yes voting tempest-api-vmware-nsxv3 正在运行 python 3.5 并且是投票的

未排序的项目

  • 应用目录
  • Chef OpenStack (Ruby)
  • Kolla:~2100 行 Python 代码,但没有“tox -e py27”目标
  • OpenStack Ansible (Python):用于部署的 Ansible 剧本和角色
  • Puppet OpenStack (Ruby)
  • TripleO

Python 2:已停止支持 Python 2.6,仅支持 Python 2.7

OpenStack Liberty 目标 Python 2.7 和 3.4。

Python 2.6 支持在 OpenStack Juno for servers 中已被停止。Python 2.6 支持当前保留在 Oslo 库和客户端中。请参阅 juno-cross-project-future-of-python etherpad。

Python 3.3 支持在 OpenStack Liberty 中已被停止。

Python 2.6 正在整个 OpenStack 项目中逐渐停止,例如:Remove p26 job from DIB

Python 2.6 支持将在 Oslo 和 Clients 客户端中为 OpenStack Mitaka 删除:Oslo libraries dropping python 2.6 compatability

将 Python 2 代码移植到 Python 3

OpenStack 项目选择使用相同的代码库来支持 Python 2 和 Python 3。Six: Python 2 and 3 Compatibility Library 有助于编写在两个版本上都能运行的代码。OpenStack 支持 RHEL 最高到 Juno 的 Python 2.6,但不支持 Python 2.5 及更早版本。由于我们正在定位 Python 3.4 及更高版本,因此无需避免 u'unicode' 语法。不要使用 six.u('unicode')。

开始之前

如果您使用 Ubuntu/Debian 进行开发(而不是使用 USE_PYTHON 标志设置的 devstack),则需要安装以下软件包才能运行项目中 py34 tox 单元测试目标

   sudo apt-get install python3.4 python3.4-dev

sixer 工具

sixer 工具有助于替换大多数基本模式以添加 Python 3 兼容性,并且它尊重 OpenStack 编码风格。

常见模式

  • 将“for key in dict.iterkeys()”替换为“for key in dict”
  • 将 dict.iteritems() 替换为 dict.items()
  • 将 dict.itervalues() 替换为 dict.values()

注意:过去首选将 dict.iteritems()/.itervalues() 替换为 six.iteritems(dict)/six.itervalues(dict),但有一个 讨论建议避免在六中对此进行操作。在 Python 2 上创建临时列表的开销可以忽略不计。

  • 将 iterator.next() 替换为 next(iterator)
  • 将 basestring 替换为 six.string_types
  • 将 unicode 替换为 six.text_type
  • 将 (str, unicode) 替换为 six.string_types
  • 将 (int, long) 替换为 six.integer_types
  • 将 func.func_name 替换为 func.__name__
  • 将 exceptions.OSError 替换为 OSError 并删除“import exceptions”
  • map() 和 filter() 如果需要 Python 3 中的列表
    • 将 map(func, data) 替换为 [func(item) for item in data]
    • 将 filter(lambda obj: test(obj), data) 替换为 [obj for obj in data if test(obj)]
    • 注意:通常,测试失败是因为 map() 或 filter() 对象没有长度

序列化:base64、JSON 等

  • [使用 oslo.serialization 1.10 或更高版本] 从 oslo_serialization(from oslo_serialization import base64)获取 base64 模块 以获取函数
    • oslo_serialization.base64.decode_as_bytes(encoded)
    • oslo_serialization.base64.decode_as_text(encoded, encoding='utf-8')
    • oslo_serialization.base64.encode_as_bytes(s, encoding='utf-8')
    • oslo_serialization.base64.encode_as_text(s, encoding='utf-8')
  • 替换 text.encode('base64') 和 base64.b64encode(text) 为
    • base64.b64encode(text):仅接受字节并返回字节,
    • 或者:oslo_serialization.base64.encode_as_bytes(text):接受字节或 Unicode 并返回字节
    • 或者:oslo_serialization.base64.encode_as_text(text):接受字节和 Unicode 并返回 Unicode
    • 警告:base64.encodestring(raw) 添加一个换行符(“\n”),而 encode_as_bytes() 和 encode_as_text() 不添加。
  • 替换 raw.decode('base64') 为
    • base64.b64decode(raw):返回字节
    • oslo_serialization.base64.decode_as_bytes(encoded):接受字节和 Unicode,返回字节
    • oslo_serialization.base64.decode_as_text(encoded):接受字节和 Unicode,返回 Unicode

十六进制

  • 替换 raw.decode('hex') 为 binascii.unhexlify(raw)
  • 替换 bytes.encode('hex') 为 binascii.hexlify(bytes)

JSON

  • [使用 oslo.serialization 1.10 或更高版本] 替换 json.dumps(obj) 为 oslo_serialization.jsonutils.dump_as_bytes(obj)
  • 替换 json.loads(obj) 为 oslo_serialization.jsonutils.loads(obj):它接受字节和 Unicode,字节从 UTF-8 解码。它避免了“if isinstance(obj, bytes): obj = obj.decode('utf-8')”,这可能需要第二个临时变量。

contextlib.nested

要替换 contextlib.nested 是使用 contextlib.ExitStack。它在 Python 2 上可用,使用 contextlib2.ExitStack。对于 contextlib.nested,nova/test.py 定义

if six.PY3:
    @contextlib.contextmanager
    def nested(*contexts):
        with contextlib.ExitStack() as stack:
            yield [stack.enter_context(c) for c in contexts]
else:
    nested = contextlib.nested

另一种替换 contextlib.nested 的方法是使用 @mock.patch 装饰器。带有嵌套函数的示例

def test_thing(self):
   @mock.patch(...)
   @mock.patch(...)
   @mock.patch(...)
   def do_test(...):
       ...
   do_test()

更多选项

oslo_utils.encodeutils.to_utf8

oslo.utils 3.5 具有一个 oslo_utils.encodeutils.to_utf8() 函数,用于将 Unicode 编码为 UTF-8 并保持字节不变。

bytes.decode 和 unicode.encode

Python 有“默认编码”的概念:sys.getdefaultencoding()。在 Python 2 上,默认编码是 ASCII,而在 Python 3 上是 UTF-8。

不要在没有参数的情况下编写 data.decode() 或 text.encode(),因为您将在 Python 2 和 Python 3 上使用不同的编码。

使用显式编码。例如:data.decode('utf-8') 或 text.encode('utf-8')。正确的编码取决于用例,但 UTF-8 通常是一个不错的选择(它是 ASCII 的超集)。

safe_decode

Olso Incubator 具有一个函数 safe_decode(),可用于解码字节字符串并保持文本字符串不变。

默认编码是 sys.stdin.encoding or sys.getdefaultencoding()

  • Python 3:区域设置编码,或者如果 sys.stdin 是“mocked”(io.StringIO 实例)则为 UTF-8
  • Python 2:区域设置编码,或者如果 stdin 不是 TTY 或如果 sys.stdin 是“mocked”(StringIO.StringIO 实例)则为 ASCII

为了不依赖于区域设置编码并在 sys.stdin 被“mocked”时具有相同的行为,最好显式指定编码。

安全用法

  • safe_decode(data, 'utf-8'):从 UTF-8 解码字节或如果已经是文本字符串则返回数据不变

不安全用法

  • safe_decode(data)

默认情况下,解码器是严格的。可以使用可选的 errors 参数指定不同的错误处理程序。例如:safe_decode(b'[\xff]', 'ascii', 'ignore') 返回 '[]'。

safe_encode

Olso Incubator 具有一个函数 safe_encode(),可用于编码字符串。它的用法很复杂,您应该了解它的工作方式以及使用了哪些编码。

  • safe_encode(text) 将文本编码为输出编码
  • safe_encode(bytes) 可能会解码字符串,然后重新编码为不同的编码,如果输入和输出编码不同

默认输入编码(incomding 参数)是 sys.stdin.encoding or sys.getdefaultencoding()

  • Python 3:区域设置编码,或者如果 sys.stdin 是“mocked”(io.StringIO 实例)则为 UTF-8
  • Python 2:区域设置编码,或者如果 stdin 不是 TTY 或如果 sys.stdin 是“mocked”(StringIO.StringIO 实例)则为 ASCII

默认输出编码(encoding 参数)是 UTF-8。

为了不依赖于区域设置编码并在 sys.stdin 被“mocked”时具有相同的行为,最好显式指定输入编码。

安全用法

  • safe_encode(data, incoming='utf-8'):将文本编码为 UTF-8 或如果已经是字节字符串则返回数据不变(因为输入和输出编码都是 UTF-8)

不安全用法

  • safe_encode(data)

示例

  • safe_encode(b'\xe9', incoming='latin-1') 返回 b'\xc3\xa9'

默认情况下,编码器和解码器是严格的。可以使用可选的 errors 参数指定不同的错误处理程序。例如:safe_encode(b'[\xff]', incoming='ascii', errors='ignore') 返回 b'[]'

logging 模块和格式化异常

oslo_utils.encodeutils 的 exception_to_unicode(exc) 函数是格式化异常为 Unicode 的推荐方法。此函数适用于 Python 2 和 Python 3,并且在大多数情况下应避免 mojibake。

在 Python 2 上,logging 模块接受字节和文本字符串。在 Python 3 上,它仅接受文本字符串。例如,logging.error(b'hello') 会记录 b'hello' 而不是 'hello'

目前还没有明确的规则来格式化异常。根据项目,有不同的选择

  • str(exc):本机字符串,因此在 Python 2 上使用字节
  • six.text_type(exc):始终使用 Unicode。它可能会根据异常引发 unicode 错误,请小心。Python 2 中的一个例子:unicode(Exception("nonascii:\xe9"))
  • six.u(str(exc)):如果在 Python 2 上 str(exc) 包含非 ASCII 字节,则不安全,例如:unicode(str(Exception("\xff")))
  • LOG.exception(_LE("... %(exc)s ..."), {"exc": exc, ...})

由于 logging 函数在 Python 3 上需要文本字符串,因此记录的异常应使用 str(exc) 格式化。例如:LOG.debug(str(exc))

HTTP

HTTP 协议基于 字节

  • HTTP 主体包含 字节。例如,使用 io.BytesIO 来存储 HTTP 主体的流。
  • HTTPConnection.getresponse().read() 返回 字节(在 Python 3 中,str 在 Python 2 中是字节)
  • 在 Python 3 上,http.client 接受文本作为 HTTP 标头:键编码为 ASCII,值编码为 ISO 8859-1(仅是 Unicode 字符集的一个小子集)
  • Swift 似乎在内部将 HTTP 标头编码为 UTF-8(直接使用 UTF-8 编码,而不是使用 MIME 编码,如 =?UTF-8?Q?...?=。请参阅 HTTP [RFC 2047 http://www.ietf.org/rfc/rfc2047.txt] 和 HTTP header should use what character encoding?

将 Python 2 代码移植到 Python 3 的参考资料

常见陷阱

什么是字符串?

在你的提交日志/评审中,绝对不要谈论“字符串”。在 Python 2 中,“字符串”是字节;在 Python 3 中,它是一个 Unicode 文本字符串。以下代码片段可能有助于理解差异

Python 2

   >>> type('foo')
   <type 'str'>
   >>> type(u'foo')
   <type 'unicode'>
   >>> type(b'foo')
   <type 'str'>
   >>> isinstance('foo', six.text_type)
   False
   >>> isinstance(u'foo', six.text_type)
   True
   >>> bytes is str
   True
   >>> b'foo'[0]
   'f'

Python 3

   >>> type('foo')
   <class 'str'>
   >>> type(u'foo')
   <class 'str'>
   >>> type(b'foo')
   <class 'bytes'>
   >>> isinstance('foo', six.text_type)
   True
   >>> isinstance(b'foo', six.text_type)
   False
   >>> bytes is str
   False
   >>> b'foo'[0]
   102

tox/testr 错误:无法确定数据库类型

“无法确定数据库类型”错误来自 testr 使用的 .testrepository/times.dbm。

解决方法:“rm -rf .testrepository/”,然后运行“tox -e py34”再运行“tox -e py27”。你只需要执行一次。当 .testrepository/ 由 Python 2 创建时,问题才会发生在使用“tox -e py34”时。

在 DevStack 中启用 Python 3

  • Fedora:
sudo dnf install python3-devel
sudo python3 -m pip install python-memcached   # needed by keystonemiddleware
  • localrc:添加以下行
USE_PYTHON3=True

参见 切换到 python 3.5

功能和集成测试

Etherpad:https://etherpad.openstack.org/p/support-python3.5-functional-tests

Doug Hellmann 编写了一个跨项目规范,用于在 Python 3 上运行集成测试:启用 Python 3 以进行应用程序集成测试(规范已获得 Liberty 的批准)。

DevStack 的补丁:启用可选的 Python 3 支持

希望将其现有的功能测试套件对服务在 Python 3 上进行测试的项目应该:-

  • 将 Python3.4 trove 分类器添加到相应服务的 setup.cfg 配置文件中。
  • 在运行 stack.sh 之前,在 Devstack 的 localrc 配置文件中设置 USE_PYTHON3=True,在 DevStack 更改 合并或 cherry-pick 之前。
  • 为必要的函数/集成测试环境在 tox 中设置 basepython = python3.5。

然后运行 tox -e<你的功能测试套件名称>。例如:tox -efunctional 运行某个项目的函数测试。

一旦功能测试套件能够可靠地通过在 python 3.5 环境中对服务的测试,则必须更新 trove 分类器,并为项目添加新的 gate 作业。

Sirushti Murugesan 在 Heat 上的尝试:https://review.openstack.org/#/c/188033/

Python 3.5

Python 3.6 状态

Python 3.6 计划成为 Ubuntu 18.04 LTS (Bionic Beaver) 和 Debian 10 (Buster) 中可用的唯一 Python 版本。

已知问题

   ENABLED_PYTHON3_PACKAGES=horizon

Linux 发行版中 Python 3 的状态

请查看 项目测试接口,以获取有关每个版本在哪些平台上进行测试的更新。

依赖项中 Python 2 支持被放弃的状态

OpenStack 计划在 U 周期开始时停止放弃 Python 2 支持

进度报告、会议和冲刺

文章

Pycon Montreal 2014:Sprint Port OpenStack to Python 3

Enovance 在 4 天内组织了一次冲刺,将 OpenStack 移植到 Python 3:2014 年 4 月 14 日(星期一)至 2014 年 4 月 17 日(星期四)。请参阅页面 Python3/SprintPycon2014