2012-09-26 11 views
5

Sto scrivendo uno script Python che accetta percorsi di file come stringhe, li analizza, aggiunge un nome di comando e crea un elenco, che viene quindi passato a subprocess.Popen() per l'esecuzione. Questo script gestisce sia i percorsi di file Unix che Windows e, in definitiva, dovrebbe essere eseguito su entrambi i sistemi.Come impedire l'escape automatico di caratteri speciali in Python

Quando eseguo questo sotto Unix, se fornisco un percorso di Windows che inavvertitamente contiene un carattere di escape (ad esempio \Users\Administrator\bin), Python interpreterà l'\b incorporato come carattere di backspace. Voglio impedire che ciò accada.

Per quanto ne so, non esiste alcuna funzione o metodo per denotare una variabile stringa come stringa non elaborata. Il modificatore 'r' funziona solo per le costanti di stringa.

Finora, la più vicina sono stato in grado di ottenere è questo:

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

A questo punto, dovrebbe contenere winpathlist ['C:','Users','Administrator','bin'], non ['C','Users','Administrator\x08in'].

posso aggiungere ulteriori chiamate a winpath.replace() per gestire le altre fughe che potrei ottenere - \a, \f, \n, \r, \t, \v - ma non \x.

Esiste un modo più pitonico per farlo?

+5

Come si ottiene il valore nella stringa? Python non dovrebbe trattare il \ b come una fuga a meno che non si trovi in ​​una stringa letterale, o entri nella stringa come una fuga per cominciare. (Inoltre, le barre di avanzamento funzionano bene.) – geoffspear

+0

@Wooble: Al momento, sta arrivando via doctest. >>> myCommandObject.setExcecutablePath ('C: \ Programmi \ cygwin \ cdrive \ bin') dove myCommandObject contiene un nome di comando (ad es. 'ps'), un percorso e un elenco di argomenti. Cambiare le barre dai backslash alle barre non è un'opzione; il mio cliente ha dichiarato esplicitamente che questo è ciò che voleva. – poltr1

+0

Come ho detto, r funziona solo con stringhe letterali; non funziona per variabili stringa. Guardo il primo r come un kluge. Comunque, ecco il doctest (o parte di esso): >>> myCommand.setExecutablePath ('C: \ Program Files \ cygwin \ cdrive \ bin') >>> myCommandList = myCommand.getLaunchList() >> > myCommandList ['C: \\\\ Programmi \\\\ cygwin \\\\ cdrive \\\\ bin \\\\ ps', '-e', '-f'] >>> myCommandList [0] .split ("\\\\") ['C:', 'Programmi', 'cygwin', 'cdrive', 'bin', 'ps'] Non ho più bisogno di errori, ora che ho aggiunto la chiamata per sostituire. – poltr1

risposta

6

Se il codice winpath è hardcoded, è possibile utilizzare r prima della stringa per indicare che è un "raw string".

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

Se winpath non può essere hard-coded, si può provare a creare una nuova stringa come:

escaped_winpath = "%r" % winpath 

(che è solo repr(winpath), e non sarà davvero aiutare, come repr("\bin") è ...)

una soluzione potrebbe essere quella di ricostruire la stringa da zero: si può trovare un esempio di funzione in that link, ma l'idea generica è:

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 

e ora, raw("\bin") ti dà "\\bin" (e non "\\x08in") ...

+0

Non ho familiarità con repr(). È in 2,6? Mi piace questa idea e mi aggrapperò a questo nel caso ne avessi bisogno in futuro. Su richiesta del mio cliente, ho estratto le chiamate a replace(). Invece, mi suggerì di spostare il test del percorso di Windows dal doctest e in un file separato. Grazie per il suggerimento. – poltr1

4

È possibile creare una stringa raw anteponendo r alla stringa notazione letterale

r"hello\nworld" 

diventa

"hello\\nworld" 

È possibile leggere altre informazioni here

+0

Negativo. Se metto la r nella stringa doctest come suggerisci, diventa parte della stringa. – poltr1

Problemi correlati