Python Literal r ‘\’ No aceptado

r'\' en Python no funciona como se esperaba. En lugar de devolver una cadena con un carácter (una barra invertida), genera un SyntaxError. r"\" hace lo mismo.

Esto es bastante engorroso si tiene una lista de rutas de Windows como estas:

 paths = [ r'\bla\foo\bar', r'\bla\foo\bloh', r'\buff', r'\', # ... ] 

¿Hay alguna buena razón por la cual este literal no es aceptado?

Esto está de acuerdo con la documentación :

Cuando hay un prefijo 'r' o 'R' , un carácter que sigue a una barra invertida se incluye en la cadena sin cambios, y todas las barras invertidas quedan en la cadena. Por ejemplo, la cadena literal r"\n" consta de dos caracteres: una barra invertida y una 'n' minúscula. Las comillas de cadena pueden escaparse con una barra invertida, pero la barra invertida permanece en la cadena; por ejemplo, r"\"" es un literal de cadena válido que consta de dos caracteres: una barra invertida y una comilla doble; r"\" no es un literal de cadena válido (incluso una cadena sin formato no puede terminar con un número impar de barras invertidas) . Específicamente, una cadena en bruto no puede terminar en una sola barra invertida (ya que la barra invertida escaparía del siguiente carácter de comillas). Tenga en cuenta que una sola barra invertida seguida de una nueva línea se interpreta como esos dos caracteres como parte de la cadena, no como una continuación de línea .

Use "\\" lugar, o, mejor aún, use / como separador de ruta (sí, esto funciona en Windows).

La barra invertida se puede usar para hacer una cita siguiente y no terminar la cadena:

 >>> r'\'' "\\'" 

Así que r'foo\' o r'\' son literales no terminados.

Razón fundamental

Debido a que solicitó específicamente el razonamiento detrás de esta decisión de diseño, los aspectos relevantes podrían ser los siguientes (aunque todo esto se basa en la especulación, por supuesto):

  • Simplifica el lexing para el intérprete de Python (todos los literales de cadena tienen la misma semántica: una cita de cierre no seguida por un número impar de barras invertidas termina la cadena)
  • Simplifica el lexing para los motores de resaltado de syntax (este es un argumento sólido porque la mayoría de los lenguajes de progtwigción no tienen cadenas crudas que aún están entre comillas simples o dobles y muchos motores de resaltado de syntax están muy dañados porque usan herramientas inapropiadas como expresiones regulares) el lexing)

Así que , probablemente haya razones importantes por las que se eligió esta forma, incluso si no está de acuerdo con estas porque cree que su caso de uso específico es más importante. Sin embargo, no lo es, por las siguientes razones:

  • Simplemente puede usar literales de cadena normales y escapar de las barras invertidas o leer las cadenas de un archivo sin procesar
  • Las barras invertidas en los literales de cadena suelen ser necesarios en uno de estos dos casos:
    • proporciona la cadena como entrada para otro intérprete de idioma que utiliza barras invertidas como un carácter de comillas, como expresiones regulares. En este caso, nunca necesitarás una barra invertida al final de una cadena
    • está utilizando \ como un separador de ruta, que generalmente no es necesario porque Python admite / como separador de ruta en Windows y porque hay os.path.sep .

Soluciones

Puedes usar '\\' o "\\" lugar:

 >>> print("\\") \ 

O si estás completamente loco, puedes usar un literal de cadena sin formato y combinarlos con literales normales solo para la barra diagonal final o incluso usar el corte de cadena:

 >>> r'C:\some\long\freakin\file\path''\\' 'C:\\some\\long\\freakin\\file\\path\\' >>> r'C:\some\long\freakin\file\path\ '[:-1] 'C:\\some\\long\\freakin\\file\\path\\' 

O, en su caso particular, podría simplemente hacer:

 paths = [ x.replace('/', '\\') for x in ''' /bla/foo/bar /bla/foo/bloh /buff / '''.strip().split()] 

Lo que le ahorraría algo de escritura al agregar más rutas, como un bono adicional.

Esto se debe a que, en cadenas sin formato, necesita una forma de evitar las comillas simples cuando la cadena está delimitada por comillas simples. Lo mismo con las comillas dobles.

http://docs.python.org/reference/lexical_analysis.html#string-literals

Para resolver su problema de raíz, puede usar / in path en Windows en Python muy bien .

La syntax de r'' y r"" (sin raw ) es principalmente para trabajar con expresiones regulares. Realmente no te da nada en el caso de trabajar con rutas como las que estás esperando, especialmente donde la cadena termina con un \ .

De lo contrario, si insiste en usar \ o use '\\' o "\\" , debe escapar del carácter de escape que es \ ; no es bonito, usar / o os.path.sep es la mejor solución.

La respuesta a mi pregunta (“¿Por qué no se permite una barra invertida como último carácter en cadenas en bruto?”) En realidad me parece “Esa es una decisión de diseño”, además de una cuestionable.

Algunas respuestas intentaron razonar que el lexer y algunos resaltadores de syntax son más simples de esta manera. No estoy de acuerdo (y tengo algunos antecedentes sobre la escritura de analizadores y comstackdores, así como el desarrollo de IDE). Sería más sencillo definir cadenas sin formato con la semántica de que una barra invertida no tiene un significado especial en absoluto. Tanto lexer como IDE se beneficiarían de esta simplificación.

La situación actual también es una verruga : en caso de que quiera una cita en una cadena en bruto, no puedo usar esto de todos modos. Solo puedo usarlo si quiero una barra invertida seguida de una cita dentro de mi cadena en bruto.

Propondría cambiar esto, pero también veo el problema de romper el código existente: – /