181 votes

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

J'ai une base de code Python, construite pour Python 3, qui utilise des open() de style Python 3 avec un paramètre d'encodage :

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

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

J'aimerais maintenant porter ce code vers Python 2.x, afin d'avoir une base de code qui fonctionne avec Python 2 et Python 3.

Quelle est la stratégie recommandée pour contourner le problème ? open() et l'absence de paramètres d'encodage ?

Pourrais-je avoir un Python 3 open() qui gère les flux de bytestrings, de sorte qu'il agirait comme Python 2 open() ?

190voto

Lennart Regebro Points 52510

1. Obtenir un paramètre d'encodage en Python 2 :

Si vous ne devez prendre en charge que 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 3.0) il est implémenté purement en Python et très lent, donc si vous avez besoin de rapidité dans la lecture des fichiers, ce n'est pas une bonne option.

Si vous avez besoin de rapidité, et que vous devez supporter Python 2.6 ou antérieur, vous pouvez utiliser codecs.open au lieu de cela. Il dispose également d'un paramètre d'encodage et est assez similaire à io.open sauf qu'il gère différemment les fins de ligne.

2. Pour obtenir un Python 3 open() qui traite les chaînes de caractères en flux continu :

open(filename, 'rb')

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

74voto

mfussenegger Points 1682

Creo que

from io import open

devrait faire.

31voto

Flimm Points 8870

En voici un exemple :

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

Voici comment faire la même chose en écrivant :

with open("filename.txt", "wb") as f:
    f.write(contents.encode("UTF-8"))

9voto

user2395922 Points 841

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)

Vous pouvez alors conserver votre code à la manière de python3.

Notez que certaines API comme newline , closefd , opener ne fonctionnent pas

2voto

YaOzI Points 129

Si vous utilisez six Vous pouvez également essayer ceci, qui utilise la dernière API de Python 3 et peut fonctionner dans les deux versions de 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.')

De plus, l'abandon du support de Python 2 supprime tout ce qui est lié à six .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X