Backporting Python 3 open (encoding = "utf-8" ) на Python 2

У меня есть кодовая база Python, созданная для Python 3, которая использует стиль Python 3 open() с параметром кодирования:

https://github.com/miohtama/vvv/blob/master/vvv/textlineplugin.py#L47

    with open(fname, "rt", encoding="utf-8") as f:

Теперь я хотел бы выполнить резервное копирование этого кода на Python 2.x, так что у меня будет кодовая база, которая работает с Python 2 и Python 3.

В чем рекомендуемая стратегия для работы с различиями open() и отсутствием параметра кодирования?

Могу ли я иметь обработчик файла стиля Python 3 open(), который передает потоки, поэтому он будет действовать как Python 2 open()?

Ответ 1

1. Чтобы получить параметр кодирования в Python 2:

Если вам нужно только поддерживать Python 2.6 и 2.7, вы можете использовать io.open вместо open. io является новой подсистемой io для Python 3, и она также существует в Python 2,6 и 2.7. Имейте в виду, что в Python 2.6 (а также 3.0) он реализован исключительно на python и очень медленный, поэтому, если вам нужна скорость чтения файлов, это не очень хороший вариант.

Если вам нужна скорость и вам нужна поддержка Python 2.6 или более ранней версии, вы можете использовать codecs.open. Он также имеет параметр кодирования и очень похож на io.open, за исключением того, что он по-разному обрабатывает окончания строк.

2. Чтобы получить обработчик файлов в стиле Python 3 open(), который передает потоковые строки:

open(filename, 'rb')

Обратите внимание на "b", что означает "двоичный".

Ответ 2

Я думаю,

from io import open

.

Ответ 3

Здесь один из способов:

with open("filename.txt", "rb") as f:
    contents = f.read().decode("UTF-8")

Ответ 4

Это может сделать трюк:

import sys
if sys.version_info[0] > 2:
    # py3k
    pass
else:
    # py2
    import codecs
    import warnings
    def open(file, mode='r', buffering=-1, encoding=None,
             errors=None, newline=None, closefd=True, opener=None):
        if newline is not None:
            warnings.warn('newline is not supported in py2')
        if not closefd:
            warnings.warn('closefd is not supported in py2')
        if opener is not None:
            warnings.warn('opener is not supported in py2')
        return codecs.open(filename=file, mode=mode, encoding=encoding,
                    errors=errors, buffering=buffering)

Затем вы можете сохранить код в пути python3.

Обратите внимание, что некоторые API, такие как newline, closefd, opener не работают

Ответ 5

Если вы используете six, вы можете попробовать это, используя последний API Python 3 и может работать как в Python 2/3:

import six

if six.PY2:
    # FileNotFoundError is only available since Python 3.3
    FileNotFoundError = IOError
    from io import open

fname = 'index.rst'
try:
    with open(fname, "rt", encoding="utf-8") as f:
        pass
        # do_something_with_f ...
except FileNotFoundError:
    print('Oops.')

И, отказ от поддержки Python 2 - это просто удаление всего, что связано с six.