web-dev-qa-db-fra.com

Pourquoi les littéraux de chaîne bruts de Python ne peuvent-ils pas se terminer par une simple barre oblique inversée?

Techniquement, tout nombre impair de barres obliques inverses, comme décrit dans la documentation .

>>> r'\'
  File "<stdin>", line 1
    r'\'
       ^
SyntaxError: EOL while scanning string literal
>>> r'\\'
'\\\\'
>>> r'\\\'
  File "<stdin>", line 1
    r'\\\'
         ^
SyntaxError: EOL while scanning string literal

Il semble que l'analyseur puisse simplement traiter les barres obliques inverses dans les chaînes brutes comme des caractères normaux (n'est-ce pas ce que sont les chaînes brutes?), Mais il me manque probablement quelque chose d'évident. TIA!

137
cdleary

La raison est expliquée dans la partie de cette section que j'ai soulignée en gras:

Les guillemets peuvent être échappés avec un backslash, mais le backslash reste le même dans la ficelle; Par exemple, r"\"" est un littéral de chaîne valide composé de deux caractères: une barre oblique inverse et un double citation; r"\" n'est pas une chaîne valide littéral (même une chaîne brute ne peut pas se terminer par un nombre impair de barres obliques inverses) . Plus précisément, une chaîne brute ne peut pas se terminer dans une seule barre oblique inversée (puisque la barre oblique inversée échapperait au caractère quote suivant). Notez également que a barre oblique inverse suivie d'une nouvelle ligne est interprété comme ces deux caractères en tant que partie de la chaîne, pas en tant que ligne continuation.

Ainsi, les chaînes brutes ne sont pas brutes à 100%, il existe encore un traitement rudimentaire de la barre oblique inverse.

105
oefe

Toute l'idée fausse qui existe à propos des chaînes brutes de python est que la plupart des gens pensent que la barre oblique inversée (dans une chaîne brute) est un caractère normal comme tous les autres. Ce n'est pas. La clé à comprendre est la séquence de tutoriels de ce python:

Lorsqu'un préfixe ' r ' ou 'R' est présent, un caractère suivant un la barre oblique inversée est incluse dans la chaîne sans modification, et toutes des barres obliques inverses sont laissées dans la chaîne

Ainsi, tout caractère suivant une barre oblique inverse fait partie de la chaîne brute. Une fois que l'analyseur entre une chaîne brute (non unicode) et rencontre une barre oblique inverse, il sait qu'il y a 2 caractères (une barre oblique inverse et un caractère le suivant).

Par ici:

r'abc\d 'comprend a, b, c, \, d

r'abc\'d' comprend a, b, c, \, ', d

r'abc\'' comprend a, b, c, \, '

et:

r'abc\'comprend a, b, c, \,' mais il n'y a pas de citation finale maintenant.

Le dernier cas montre que selon la documentation, un analyseur syntaxique ne peut pas trouver de devis de clôture car le dernier itinéraire que vous voyez ci-dessus fait partie de la chaîne, c'est-à-dire. La barre oblique inversée ne peut pas être la dernière ici car elle «dévorera» le caractère de fermeture de la chaîne.

67
Artur

C'est comme ça! Je le vois comme un de ces petits défauts en python!

Je ne pense pas que ce soit une bonne raison, mais ce n'est certainement pas une analyse syntaxique; il est très facile d'analyser les chaînes brutes avec\comme dernier caractère.

Le problème est que, si vous autorisez que\soit le dernier caractère d'une chaîne brute, vous ne pourrez pas insérer "dans une chaîne brute. Il semble que python a opté pour autoriser" au lieu d'autoriser\comme dernier caractère.

Cependant, cela ne devrait causer aucun problème.

Si vous ne pouvez pas écrire facilement les chemins de dossiers Windows tels que c:\mypath\, ne vous inquiétez pas, vous pouvez les représenter en tant que r"C:\mypath" et, si vous devez ajouter un nom de sous-répertoire, ne le faites pas avec la concaténation de chaînes car ce n’est pas la bonne façon de le faire quand même! utiliser os.path.join

>>> import os
>>> os.path.join(r"C:\mypath", "subfolder")
'C:\\mypath\\subfolder'
19
hasen

Une autre astuce consiste à utiliser chr (92) car il s’évalue à "\". 

J'ai récemment dû nettoyer une chaîne de barres obliques inverses et voici ce qui s'est passé:

CleanString = DirtyString.replace(chr(92),'')

Je me rends compte que cela ne prend pas en compte le "pourquoi" mais que le fil attire beaucoup de personnes à la recherche d'une solution à un problème immédiat.

13
Geekworking

Pour que vous puissiez terminer une chaîne brute avec une barre oblique, je vous suggère d'utiliser cette astuce

>>> print r"c:\test"'\\'
test\
10
Charles Beattie

Étant donné que\"est autorisé dans la chaîne brute, il ne peut pas être utilisé pour identifier la fin du littéral de chaîne. 

Pourquoi ne pas arrêter d’analyser le littéral chaîne lorsque vous rencontrez le premier "?

Si c'était le cas,\"ne serait pas autorisé à l'intérieur du littéral chaîne. Mais c'est le cas.

8
Brian R. Bondy

La raison pour laquelle r'\' est syntaxiquement incorrect est que, bien que l'expression de chaîne soit brute, les guillemets utilisés (simples ou doubles) doivent toujours être échappés, car ils marqueraient la fin de la citation. Donc, si vous souhaitez exprimer un seul guillemet dans une chaîne entre guillemets, il n'y a pas d'autre moyen que d'utiliser \'. Même chose pour les guillemets doubles.

Mais vous pouvez utiliser:

'\\'
4
Gumbo

Un autre utilisateur qui a depuis supprimé sa réponse (ne sachant pas s'il souhaitait être crédité) a suggéré que les concepteurs de langage Python pourraient peut-être simplifier la conception de l'analyseur en utilisant les mêmes règles d'analyse et en développant les caractères masqués sous leur forme brute après coup. (si le littéral a été marqué comme brut).

Je pensais que c'était une idée intéressante et je l'inclue en tant que wiki communautaire pour la postérité.

2
cdleary

Malgré son rôle, même une chaîne brute ne peut pas se terminer par un seul barre oblique inverse, car la barre oblique inverse échappe à la citation suivante caractère - vous devez toujours échapper le caractère de citation qui l'entoure à l'intégrer dans la chaîne. C’est-à-dire que r "... \" n’est pas une chaîne valide littéral: une chaîne brute ne peut pas se terminer par un nombre impair de barres obliques inverses.
Si vous devez terminer une chaîne brute avec une simple barre oblique inverse, vous pouvez utiliser deux et trancher la seconde.

1
pawandeep singh

En venant de C, il est assez clair pour moi qu'un simple\fonctionne comme un caractère d'échappement vous permettant de mettre des caractères spéciaux tels que des nouvelles lignes, des tabulations et des guillemets dans des chaînes.

Ceci n'autorise en effet pas le dernier caractère car il échappera à "et fera étouffer l'analyseur. Mais comme indiqué plus tôt\est légal.

1
Robert Ahlskog

J'ai rencontré ce problème et trouvé une solution partielle qui convient à certains cas. Bien que python ne puisse pas terminer une chaîne avec une simple barre oblique inverse, celle-ci peut être sérialisée et enregistrée dans un fichier texte avec une seule barre oblique inverse à la fin. Par conséquent, si vous avez besoin d’enregistrer un texte avec une simple barre oblique inverse sur votre ordinateur, il est possible:

x = 'a string\\' 
x
'a string\\' 

# Now save it in a text file and it will appear with a single backslash:

with open("my_file.txt", 'w') as h:
    h.write(x)

BTW ne fonctionne pas avec json si vous le dumpez en utilisant la bibliothèque json de python. 

Enfin, je travaille avec Spyder, et j’ai remarqué que si j’ouvre la variable dans l’éditeur de texte de spider en double-cliquant sur son nom dans la variable Explorer, elle est présentée avec une simple barre oblique inverse et peut être copiée dans le presse-papier très utile pour la plupart des besoins mais peut-être pour certains ..). 

0
BossaNova

quelques conseils :

1) Si vous devez manipuler une barre oblique inversée pour le chemin, le module standard python os.path est votre ami. par exemple : 

os.path.normpath ('c:/dossier1 /')

2) si vous voulez construire des chaînes avec une barre oblique inversée MAIS sans barre oblique inverse à la fin de votre chaîne, la chaîne brute est votre ami (utilisez le préfixe 'r' avant votre chaîne littérale). par exemple : 

r'\one \two \three'

3) si vous avez besoin de préfixer une chaîne dans une variable X avec une barre oblique inverse, procédez comme suit:

X='dummy'
bs=r'\ ' # don't forget the space after backslash or you will get EOL error
X2=bs[0]+X  # X2 now contains \dummy

4) si vous avez besoin de créer une chaîne avec une barre oblique inverse à la fin, combinez les astuces 2 et 3:

voice_name='upper'
lilypond_display=r'\DisplayLilyMusic \ ' # don't forget the space at the end
lilypond_statement=lilypond_display[:-1]+voice_name

maintenant lilypond_statement contient "\DisplayLilyMusic \upper"

vive le python! :)

n3on

0
n3on