En écrivant mon code pour Python 2.6, mais en pensant à Python 3, j’ai pensé que c’était une bonne idée de mettre
from __future__ import unicode_literals
au sommet de certains modules. En d'autres termes, je demande des ennuis (pour les éviter à l'avenir), mais il se peut que je manque quelques connaissances importantes ici. Je veux pouvoir passer une chaîne représentant un chemin de fichier et instancier un objet aussi simple que
MyObject('H:\unittests')
Dans Python 2.6, cela fonctionne très bien, pas besoin d’utiliser des doubles barres obliques inverses ou une chaîne brute, même pour un répertoire commençant par '\u..'
, ce qui est exactement ce que je veux. Dans la méthode __init__
, je m'assure que toutes les occurrences uniques \
sont interprétées comme '\\
', y compris celles précédant les caractères spéciaux comme dans \a
, \b
, \f
, \n
, \r
, \t
et \v
(seul \x
reste un problème). Décoder également la chaîne donnée en unicode à l'aide d'un codage (local) fonctionne comme prévu.
Se préparer pour Python 3.xEn simulant mon problème actuel dans un éditeur (à partir d’une console vierge dans Python 2.6), il se passe ce qui suit:
>>> '\u'
'\\u'
>>> r'\u'
'\\u'
(OK jusqu'à ici: '\u'
est codé par la console en utilisant le codage local)
>>> from __future__ import unicode_literals
>>> '\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence
En d'autres termes, la chaîne (unicode) n'est pas du tout interprétée comme unicode et n'est pas décodée automatiquement avec le codage local. Néanmoins, pour une chaîne brute:
>>> r'\u'
SyntaxError: (unicode error) 'rawunicodeescape' codec can't decode bytes in position 0-1: truncated \uXXXX
idem pour u'\u'
:
>>> u'\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence
De plus, je m'attendrais à ce que isinstance(str(''), unicode)
renvoie True
(ce qui n'est pas le cas), car l'importation d'unligne_literals devrait rendre tous les types de chaînes unicode. (modifier:) Parce que dans Python 3, toutes les chaînes sont des séquences de caractères Unicode , je suppose que str(''))
retournera une telle chaîne-unicode et que type(str(''))
sera à la fois <type 'unicode'>
et <type 'str'>
(car toutes les chaînes sont unicode), mais réalisent également que <type 'unicode'> is not <type 'str'>
. Confusion tout autour ...
Des questions
\u
'? (sans écrire '\\u
')from __future__ import unicode_literals
implémente-t-il réellement toutes les modifications unicode liées à Python 3. afin que je reçoive un environnement complet de chaînes Python 3?edit: En Python 3, <type 'str'>
est un objet Unicode et <type 'unicode'>
n'existe tout simplement pas. Dans mon cas, je veux écrire du code pour Python 2(.6) qui fonctionnera sous Python 3. Mais lorsque je import unicode_literals
, je ne peux pas vérifier si une chaîne est de <type 'unicode'>
car:
unicode
ne fait pas partie de l'espace de nomsunicode
fait partie de l'espace de noms, un littéral de <type 'str'>
est toujours unicode lorsqu'il est créé dans le même moduletype(mystring)
retournera toujours <type 'str'>
pour les littéraux unicode dans Python 3Mes modules sont encodés dans 'utf-8' par un commentaire # coding: UTF-8
en haut, alors que mon locale.getdefaultlocale()[1]
renvoie 'cp1252'. Donc, si j'appelle MyObject('çça')
depuis ma console, il est codé comme «cp1252» dans Python 2 et dans «utf-8» lors de l'appel de MyObject('çça')
à partir du module. En Python 3, il ne sera pas codé, mais littéral unicode.
modifier:
J'ai abandonné tout espoir de pouvoir éviter d'utiliser '\' avant une u
(ou x
d'ailleurs). De plus, je comprends les limites de l’importation de unicode_literals
. Cependant, les nombreuses combinaisons possibles consistant à passer une chaîne d'un module à la console et à inverser vica avec chaque encodage différent, et en plus d'importer unicode_literals
ou non et Python 2 vs Python 3, m'ont donné envie de créer une vue d'ensemble en testant réellement . D'où le tableau ci-dessous.
En d'autres termes, type(str(''))
ne renvoie pas <type 'str'>
en Python 3, mais <class 'str'>
et tous les problèmes de Python 2 semblent être évités.
Si je comprends bien, tout ce que from __future__ import unicode_literals
fait, c'est de créer tous les littéraux de chaîne de type unicode, au lieu de type de chaîne. C'est:
>>> type('')
<type 'str'>
>>> from __future__ import unicode_literals
>>> type('')
<type 'unicode'>
Mais str
et unicode
sont toujours des types différents et se comportent exactement comme avant.
>>> type(str(''))
<type 'str'>
Toujours, est de type str
.
En ce qui concerne votre problème r'\u'
, il est inhérent à la conception, car il équivaut à ru '\ u' sans unicode_literals
. De la docs:
Lorsqu'un préfixe "r" ou "R" est utilisé conjointement avec un préfixe "u" ou "U", les séquences d'échappement\uXXXX et\UXXXXXXXX sont traitées alors que toutes les autres barres obliques inverses sont laissées dans la chaîne.
Probablement de la manière dont l'analyseur lexical a fonctionné dans la série python2. En python3, cela fonctionne comme vous le souhaiteriez.
Vous pouvez taper la barre oblique inverse deux fois, puis le \u
ne sera pas interprété, mais vous obtiendrez deux barres obliques inverses!
Les barres obliques inverses peuvent être masquées avec une barre oblique inverse précédente. cependant, les deux restent dans la chaîne
>>> ur'\\u'
u'\\\\u'
Donc, à mon humble avis, vous avez deux options simples:
N'utilisez pas de chaînes brutes et échappez vos barres obliques inverses (compatibles avec python3):
'H:\\unittests'
Soyez trop intelligent et tirez parti des points de code Unicode ( pas compatibles avec python3):
r'H:\u005cunittests'
Pour moi, ce problème était lié à la version non à jour, dans ce cas numpy
Pour réparer:
conda install -f numpy