如何编写单源兼容 Python 2/3 代码以从内存中的字符串写入文本文件
How to write single-source compatible Python 2/3 code to write text files from in-memory strings
我有一堆 Python 2.7 代码,我正在尝试使它们与 Python 3 的单源兼容,以帮助随着时间的推移从 2.7 迁移。我看到的最常见问题是将非 unicode
内存内容简单写入磁盘。例如:
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(json.dumps(some_object, indent=2)))
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(yaml.dump(some_object, default_flow_style=False))) # From PyYAML
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(some_multiline_string)) # A simple string passed in, not explicitly marked up as unicode where it was declared
当然,unicode
的转换在 Python 3 下失败,因为该类型不存在。如果我改变演员阵容,它就像:
the_file.write(str(json.dumps(some_object, indent=2)))
然后它在 Python 3 中工作,但在 Python 2 下失败,因为 str
和 unicode
是不同的,并且 file.write
需要一个 unicode 参数.虽然 json.dumps
调用可以适应直接使用文件的 json.dump
调用,但据我所知,yaml 转储调用不能。
理想情况下,会有一种方法可以将所有正在写入的内容的类型强制转换为 file.write
想要的类型(unicode 字符串),但我找不到那是什么。我曾希望您总是能够将各种形式的非 unicode 字符串 decode
转换为 unicode 字符串,但是 Python 2 中的 str
个对象似乎没有 decode
函数。
我发现的所有其他问题(在 Stack Overflow 和其他地方)和文档都提供了相互矛盾的建议,关注缓冲区对象,或者只是就如何在 [=35= 的一个版本中执行此操作提供建议] 或其他。我需要一个在 Python 2.7 和 3.x 中同样有效的解决方案,我希望有一个优雅的 Python-esque 解决方案,不涉及分支测试检测正在使用的版本。
因此,根据评论中的建议,我选择了 six module. Version 1.12.0 and higher includes six.ensure_text,这是我在问题中描述的“强制写入 [unicode] 的所有内容的类型的方法”。
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(json.dumps(some_object, indent=2)))
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(yaml.dump(some_object, default_flow_style=False))) # From PyYAML
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(some_multiline_string)) # A simple string passed in, not explicitly marked up as unicode where it was declared
我遇到了一些版本兼容性问题(我依赖的其他 pip 模块似乎需要 six
1.11.0
),但我已经解决了这些问题,所提供的功能可以在我们所有现有代码中干净利落地使用。
我有一堆 Python 2.7 代码,我正在尝试使它们与 Python 3 的单源兼容,以帮助随着时间的推移从 2.7 迁移。我看到的最常见问题是将非 unicode
内存内容简单写入磁盘。例如:
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(json.dumps(some_object, indent=2)))
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(yaml.dump(some_object, default_flow_style=False))) # From PyYAML
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(unicode(some_multiline_string)) # A simple string passed in, not explicitly marked up as unicode where it was declared
当然,unicode
的转换在 Python 3 下失败,因为该类型不存在。如果我改变演员阵容,它就像:
the_file.write(str(json.dumps(some_object, indent=2)))
然后它在 Python 3 中工作,但在 Python 2 下失败,因为 str
和 unicode
是不同的,并且 file.write
需要一个 unicode 参数.虽然 json.dumps
调用可以适应直接使用文件的 json.dump
调用,但据我所知,yaml 转储调用不能。
理想情况下,会有一种方法可以将所有正在写入的内容的类型强制转换为 file.write
想要的类型(unicode 字符串),但我找不到那是什么。我曾希望您总是能够将各种形式的非 unicode 字符串 decode
转换为 unicode 字符串,但是 Python 2 中的 str
个对象似乎没有 decode
函数。
我发现的所有其他问题(在 Stack Overflow 和其他地方)和文档都提供了相互矛盾的建议,关注缓冲区对象,或者只是就如何在 [=35= 的一个版本中执行此操作提供建议] 或其他。我需要一个在 Python 2.7 和 3.x 中同样有效的解决方案,我希望有一个优雅的 Python-esque 解决方案,不涉及分支测试检测正在使用的版本。
因此,根据评论中的建议,我选择了 six module. Version 1.12.0 and higher includes six.ensure_text,这是我在问题中描述的“强制写入 [unicode] 的所有内容的类型的方法”。
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(json.dumps(some_object, indent=2)))
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(yaml.dump(some_object, default_flow_style=False))) # From PyYAML
with io.open(some_path, 'w', encoding='utf-8') as the_file:
the_file.write(six.ensure_text(some_multiline_string)) # A simple string passed in, not explicitly marked up as unicode where it was declared
我遇到了一些版本兼容性问题(我依赖的其他 pip 模块似乎需要 six
1.11.0
),但我已经解决了这些问题,所提供的功能可以在我们所有现有代码中干净利落地使用。