2012-09-26 13 views
5

Piszę skrypt w języku Python, który akceptuje ścieżki plików jako łańcuchy, analizuje je, dodaje nazwę polecenia i buduje listę, która następnie jest przekazywana do wykonania przez subprocess.Popen(). Skrypt ten obsługuje zarówno ścieżki plików Unix, jak i Windows, a docelowo powinien działać w obu systemach.Jak zapobiec automatycznym zmianom znaków specjalnych w Pythonie

Po uruchomieniu tego w systemie Unix, jeśli podam ścieżkę systemu Windows, która nieumyślnie zawiera znak escape (np. \Users\Administrator\bin), Python zinterpretuje osadzoną \b jako znak Backspace. Chcę temu zapobiec.

O ile mi wiadomo, nie ma funkcji lub metody oznaczania zmiennej łańcuchowej jako nieprzetworzonego łańcucha. Modyfikator 'r' działa tylko dla stałych łańcuchowych.

Dotychczas najbliżej byłem w stanie uzyskać to:

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

W tym momencie powinno winpathlist zawierać ['C:','Users','Administrator','bin'], nie ['C','Users','Administrator\x08in'].

mogę dodać dodatkowe połączenia do winpath.replace() do obsługi innych ucieczek mogę dojechać - \a, \f, \n, \r, \t, \v - ale nie \x.

Czy jest to bardziej pythonic sposób to zrobić?

+5

Jak otrzymujesz wartość do ciągu? Python nie powinien traktować \ b jako ucieczki, chyba że jest w literale łańcuchowym, lub wchodzi do łańcucha jako ucieczka na początek. (Również ukośniki działają dobrze.) – geoffspear

+0

@Wooble: W tej chwili przychodzi za pośrednictwem doctest. >>> myCommandObject.setExcecutablePath ("C: \ Program Files \ cygwin \ cdrive \ bin") gdzie myCommandObject zawiera nazwę polecenia (np. "ps"), ścieżkę i listę argumentów. Zmiana ukośników z ukośników odwrotnych na ukośniki nie jest opcją; mój klient wyraźnie stwierdził, że tego właśnie chciał. – poltr1

+0

Jak już powiedziałem, r działa tylko dla literałów ciągowych; nie działa dla zmiennych łańcuchowych. Patrzę na prowadzący r jako kluczyk. W każdym razie, oto doctest (lub jego część): >>> myCommand.setExecutablePath ('C: \ Program Files \ cygwin \ cdrive \ bin') >>> myCommandList = myCommand.getLaunchList() >> > myCommandList ['C: \\\\ Program Files \\\\ cygwin \\\\ cdrive \\\\ bin \\\\ ps', '-e', '-f'] >>> myCommandList [0] .split ("\\\\") ['C:', 'Program Files', 'cygwin', 'cdrive', 'bin', 'ps'] Nie otrzymuję już żadnych błędy, teraz dodałem wezwanie do zastąpienia. – poltr1

Odpowiedz

6

Jeśli Twój winpath jest zakodowany na stałe, możesz użyć przed ciągiem znaków r, aby wskazać, że jest to "raw string".

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

Jeśli winpath nie może być ustalony, można spróbować utworzyć nowy ciąg jako:

escaped_winpath = "%r" % winpath 

(który jest po prostu repr(winpath) i nie będzie naprawdę pomóc, jak repr("\bin") jest ...)

rozwiązaniem byłoby odbudować ciąg od podstaw: można znaleźć przykład funkcji w that link, ale ogólny pomysł jest:

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 

i teraz, raw("\bin") daje "\\bin" (i nie "\\x08in") ...

+0

Nie jestem zaznajomiony z repr(). Czy to w 2.6? Podoba mi się ten pomysł i będę go trzymał na wypadek, gdyby potrzebowałem go w przyszłości. Na życzenie mojego klienta, wyciągnąłem wezwania do zastąpienia(). Zamiast tego zasugerował, aby przenieść test ścieżki systemu Windows z testu do osobnego pliku. Dzieki za sugestie. – poltr1

4

Można utworzyć ciąg surowego przez poprzedzenie r na ciąg notacji dosłowne

r"hello\nworld" 

staje

"hello\\nworld" 

Możesz przeczytać więcej here

+0

Negatywny. Jeśli wstawię r w ciąg doctest, jak sugerujesz, staje się częścią ciągu. – poltr1

Powiązane problemy