2012-09-26 77 views
5

Estoy escribiendo un script de Python que acepta rutas de archivos como cadenas, las analiza, agrega un nombre de comando y crea una lista, que luego se pasa al subprocess.Popen() para su ejecución. Este script es para manejar rutas de archivos de Unix y Windows, y finalmente debe ejecutarse en ambos sistemas.Cómo prevenir el escape automático de caracteres especiales en Python

Cuando ejecuto esto en Unix, si proporciono una ruta de Windows que inadvertidamente contiene un carácter de escape (por ejemplo, \Users\Administrator\bin), Python interpretará el \b incrustado como el carácter de retroceso. Quiero evitar que eso suceda.

Hasta donde yo sé, no hay ninguna función o método para denotar una variable de cadena como una cadena sin formato. El modificador 'r' solo funciona para constantes de cadena.

Hasta el momento, lo más cerca que he sido capaz de conseguir es la siguiente:

winpath = "C:\Users\Administrator\bin" 
winpath = winpath.replace('\b','\\b') 
winpathlist = winpath.split('\\') 

En este punto, debe contener winpathlist ['C:','Users','Administrator','bin'], no ['C','Users','Administrator\x08in'].

puedo añadir llamadas adicionales a winpath.replace() para manejar el otro escapa que podría conseguir - \a, \f, \n, \r, \t, \v - pero no \x.

¿Hay una manera más pitonica de hacer esto?

+5

¿Cómo está obteniendo el valor en la cadena? Python no debería tratar el \ b como un escape a menos que esté en un literal de cadena, o se meta en la cadena como un escape para empezar. (Además, las barras diagonales funcionan bien) – geoffspear

+0

@Wooble: ahora mismo, entra por doctest. >>> myCommandObject.setExcecutablePath ('C: \ Archivos de programa \ cygwin \ cdrive \ bin') donde myCommandObject contiene un nombre de comando (por ejemplo 'ps'), una ruta y una lista de argumentos. Cambiar las barras desde barras invertidas a barras diagonales no es una opción; mi cliente declaró explícitamente que esto es lo que quería. – poltr1

+0

Como dije, r solo funciona para literales de cadena; no funciona para las variables de cadena. Miro a la r principal como un kluge. De todos modos, aquí está el doctest (o parte de ella): >>> myCommand.setExecutablePath ('C: \ Archivos de programa \ cygwin \ cdrive \ bin') >>> myCommandList = myCommand.getLaunchList() >> > myCommandList ['C: \\\\ Archivos de programa \\\\ cygwin \\\\ cdrive \\\\ bin \\\\ ps', '-e', '-f'] >>> myCommandList [0] .split ("\\\\") ['C:', 'Archivos de programa', 'cygwin', 'cdrive', 'bin', 'ps'] Ya no recibo ninguna errores, ahora que agregué la llamada para reemplazar. – poltr1

Respuesta

6

Si su winpath está codificado, es posible que desee utilizar r antes de su cadena para indicar que es "raw string".

winpath = r"C:\Users\Administrator\bin" 

Si winpath no puede ser codificada de manera no, se puede tratar de crear una nueva cadena como:

escaped_winpath = "%r" % winpath 

(que es sólo repr(winpath) y no realmente le ayudará, como repr("\bin") es ...)

una solución sería la de reconstruir la cadena de cero: se puede encontrar un ejemplo de función en that link, pero la idea genérica es:

escape_dict={'\a':r'\a', 
      '\b':r'\b', 
      '\c':r'\c', 
      '\f':r'\f', 
      '\n':r'\n', 
      '\r':r'\r', 
      '\t':r'\t', 
      '\v':r'\v', 
      '\'':r'\'', 
      '\"':r'\"'} 

def raw(text): 
    """Returns a raw string representation of text""" 
    new_string='' 
    for char in text: 
     try: 
      new_string += escape_dict[char] 
     except KeyError: 
      new_string += char 
    return new_string 

y ahora, raw("\bin") le da "\\bin" (y no "\\x08in") ...

+0

No estoy familiarizado con repr(). ¿Está en 2.6? Me gusta esta idea, y me aferraré a esto en caso de que la necesite en el futuro. A pedido de mi cliente, saqué las llamadas para reemplazar(). En cambio, sugirió que pase la prueba de ruta de Windows fuera del doctest a un archivo separado. Gracias por la sugerencia. – poltr1

4

Puede crear una cadena de texto en anteponiendo r para la cadena de la notación literal

r"hello\nworld" 

convierte

"hello\\nworld" 

Puede leer más here

+0

Negativo. Si pongo el r en la cadena más doctest como sugieres, se convierte en parte de la cadena. – poltr1

Cuestiones relacionadas