web-dev-qa-db-fra.com

Backporting Python 3 ouvert (encodage = "utf-8") à Python 2

J'ai un Python codebase, construit pour Python 3, qui utilise le style Python 3 open () avec le paramètre d'encodage:

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

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

Maintenant, je voudrais effectuer un backport de ce code vers Python 2.x, de manière à disposer d'un code de base fonctionnant avec Python 2 et Python 3.

Quelle est la stratégie recommandée pour contourner open() différences et manque de paramètre de codage?

Pourrais-je avoir un gestionnaire de fichier de style Python 3 open() qui diffuse des chaînes de caractères, de sorte qu'il se comporte comme Python 2 open()?

140
Mikko Ohtamaa

1. Pour obtenir un paramètre de codage dans Python 2:

Si vous avez seulement besoin de supporter Python 2.6 et 2.7, vous pouvez utiliser io.open au lieu de open. io est le nouveau sous-système io pour Python 3, et il existe également dans Python 2,6 et 2,7. Sachez que dans Python 2.6 (ainsi que dans la version 3.0), il est implémenté uniquement dans python et très lentement. Par conséquent, si vous avez besoin de vitesse de lecture, ce n’est pas une bonne option.

Si vous avez besoin de rapidité ou si vous devez prendre en charge Python 2.5 ou version antérieure, vous pouvez utiliser codecs.open . Il possède également un paramètre de codage et est assez similaire à _io.open_ sauf qu’il gère les fins de ligne différemment.

2. Pour obtenir un gestionnaire de fichiers de style Python 3 open() qui diffuse des chaînes d'octets:

_open(filename, 'rb')
_

Notez le "b", qui signifie "binaire".

163
Lennart Regebro

Je pense

from io import open

devrait faire.

60
mfussenegger

Voici un moyen:

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

Cela peut faire l'affaire:

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)

Ensuite, vous pouvez garder votre code de la manière python3.

Notez que certaines API telles que newline, closefd, opener ne fonctionnent pas.

8
user2395922

Si vous utilisez six , vous pouvez essayer d’utiliser la dernière API Python 3 et de l’exécuter à la fois 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.')

Et, Python 2 support abandon, supprime simplement tout ce qui concerne six.

1
YaOzI