파이썬의 원시 문자열 리터럴이 단일 백 슬래시로 끝나지 않는 이유는 무엇입니까?


179

기술적 슬래시 중 홀수,로 기술 문서 .

>>> 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

파서는 원시 문자열의 백 슬래시를 일반 문자로 처리 할 수있는 것처럼 보입니다 (원시 문자열이 무엇입니까?)


8
이것은 이제 faq 입니다. 질문했을 때가 아닐 수도 있습니다. 나는 당신이 인용 한 문서가 거의 똑같은 것을 말하지만, 나는 단지 다른 문서 소스를 추가 할 것이라고 생각했습니다.
oob

답변:


124

그 이유는 해당 섹션에서 굵게 강조 표시된 부분에 설명되어 있습니다.

문자열 인용 부호는 백 슬래시로 이스케이프 할 수 있지만 백 슬래시는 문자열에 남아 있습니다. 예를 들어, r"\""두 개의 문자 : 백 슬래시와 큰 따옴표로 구성된 유효한 문자열 리터럴입니다. r"\"유효한 문자열 리터럴이 아닙니다 (원시 문자열도 홀수의 백 슬래시로 끝날 수 없음). 특히, 원시 문자열은 단일 백 슬래시로 끝날 수 없습니다 (백 슬래시는 다음 따옴표 문자를 이스케이프하므로). 또한 단일 백 슬래시와 개행 문자는 줄 연속으로가 아니라 문자열의 일부로이 두 문자로 해석됩니다.

따라서 원시 문자열은 100 % 원시가 아니며 여전히 기본적인 백 슬래시 처리가 있습니다.


21
오 와우 .. 이상해. 잘 잡았다. r '\' '== "\\'"라는 것이 이치에 맞지만 이스케이프 문자가 사라지지 않고 효과가 있다는 것은 여전히 ​​이상합니다.
cdleary

2
@ihightower 이것은 파일 시스템 경로에서 작동하지만 백 슬래시의 다른 용도가 있습니다. 파일 시스템 경로의 경우 구분 기호를 하드 코딩하지 마십시오. 'os.path.sep'를 사용하거나 'os.path'의 상위 레벨 기능을 사용하십시오. (또는 가능하면 'pathlib')
oefe

5
참고 : 해결 방법은 인접한 리터럴 연결을 사용하는 것입니다. r"foo\bar\baz" "\\"(모호한 경우 괄호로 묶음) 컴파일 타임에 단일 리터럴을 작성합니다. 첫 번째 부분은 원시이고 마지막 작은 비트 만 원시가 아닙니다. 후행 백 슬래시를 허용합니다.
ShadowRanger

2
IMO는 이것이 왜 이런 식으로 설계되었는지 말하지 않고 질문 (허용되는 것 / 작동하는 것, 그렇지 않은 것)을 재조정합니다. 그 이유를 설명 하는 FAQ 항목 이 있습니다 (원시 문자열은 특정 목적을 위해 설계되었으며 해당 목적의 맥락에서 의미가 있습니다).
ShreevatsaR

3
원시 문자열의 요점은 무엇입니까? 개념의 그늘진 구현처럼 보입니다.
Matthew James Briggs

101

파이썬의 원시 문자열에 대한 오해는 대부분의 사람들이 원시 문자열 내에서 백 슬래시가 다른 모든 문자와 마찬가지로 일반적인 문자라고 생각한다는 것입니다. 아닙니다. 이해하는 열쇠는이 파이썬의 튜토리얼 순서입니다.

' r '또는 ' R '접두사가 있으면 백 슬래시 뒤에 오는 문자가 변경없이 문자열에 포함되고 모든 백 슬래시는 문자열에 남습니다.

그래서 백 슬래시 다음에 오는 모든 문자 입니다 원시 문자열의 일부. 파서가 원시 문자열 (유니 코드가 아닌 문자열)을 입력하고 백 슬래시가 발생하면 2 개의 문자 (백 슬래시와 그 뒤에 오는 문자)가 있음을 알게됩니다.

이 방법:

r'abc \ d 'a, b, c, \, d로 구성됩니다.

r'abc \ 'd'a, b, c, \, ', d로 구성됩니다.

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

과:

r'abc \ 'a, b, c, \,'로 구성 되지만 현재 종료 인용은 없습니다.

마지막 사례는 문서에 따르면 파서가 위에서 본 마지막 따옴표가 문자열의 일부이므로 닫는 따옴표를 찾을 수 없다는 것을 보여줍니다.


8
이것은 실제로 허용 된 답변보다 명확합니다. 좋은 고장.
Mad Physicist

4
나는 또한 이것이 받아 들여진 대답보다 훨씬 더 명확하다는 것을 발견하고 물리학 자이기도하다
xdavidliu

22

즉,이 방법! 나는 그것을 파이썬의 작은 결함 중 하나로 봅니다!

나는 그럴만한 이유가 없다고 생각하지만, 확실히 파싱하지는 않는다. \를 마지막 문자로 사용하여 원시 문자열을 구문 분석하는 것은 정말 쉽습니다.

캐치는 \를 원시 문자열의 마지막 문자로 허용하면 원시 문자열 안에 "를 넣을 수 없습니다. 파이썬은 \를 마지막 문자로 허용하는 대신"를 허용하는 것처럼 보입니다.

그러나 이로 인해 문제가 발생하지 않아야합니다.

Windows 폴더 경로를 쉽게 작성할 수없는 것에 대해 c:\mypath\걱정할 경우 걱정하지 마십시오.로 표시 할 수 r"C:\mypath"있으며 하위 디렉토리 이름을 추가해야하는 경우 문자열 연결로 수행하지 마십시오. 어쨌든 그것을하는 올바른 방법이 아닙니다! 사용하다os.path.join

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

2
좋은 보조 재료. :-) 그러나 Devil의 옹호자는 때때로 경로 구분 기호를 추가하여 파일 경로를 디렉토리 경로와 구별하려고합니다. os.path.join의 좋은 점은 그것들이 축소된다는 것입니다 : assert os.path.join ( '/ home / cdleary /', 'foo /', 'bar /') == '/ home / cdleary / foo / bar / '
cdleary

그래도 (기술적 인) 차이는 없습니다! os.path.isdir 특정 경로가 디렉토리 (폴더)인지를 알려줍니다
하센

2
그렇습니다. 경로가 디렉토리인지 파일인지를 코드를 읽는 사람에게 나타냅니다.
cdleary

창에 대한 규칙은 파일 확장자가 항상 있다는 것입니다. c : \ path \ data와 같은 경로를 가진 텍스트 파일을 가질 가능성은 거의 없습니다 (정상적인 상황에서)
has

5
또는 "c : / mypath"로 표시하고 백 슬래시 문제를 모두 잊을 수 있습니다. :-)
John Fouhy

14

슬래시로 원시 문자열을 끝내려면이 트릭을 사용할 수 있습니다.

>>> print r"c:\test"'\\'
test\

14

또 다른 트릭은 chr (92)를 "\"로 평가하는 것입니다.

나는 최근에 백 슬래시 문자열을 청소해야했고 다음과 같은 트릭이있었습니다.

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

나는 이것이 "왜"를 돌보지 않지만 스레드는 즉각적인 문제에 대한 해결책을 찾는 많은 사람들을 끌어 들인다는 것을 알고 있습니다.


그러나 원래 문자열에 백 슬래시가 포함되어 있으면 어떻게됩니까?
Joseph Redfern

2
chr (92)는 끔찍하게 불분명하고 아마도 사용하는 것이 더 좋습니다 "\\"(백 슬래시가있는 비원시 문자열)
clemep

9

\ "는 원시 문자열 내부에서 허용되므로 문자열 리터럴의 끝을 식별하는 데 사용할 수 없습니다.

첫 번째 ""가 발생할 때 문자열 리터럴 구문 분석을 중지하지 않으시겠습니까?

이 경우 문자열 리터럴 안에 \ "를 사용할 수 없습니다. 그러나 그렇습니다.


1
바로 그거죠. 파이썬 디자이너는 두 가지 대안의 가능성을 평가할 \"수 있습니다. 즉, 큰 따옴표로 묶인 원시 문자열 내의 두 문자 시퀀스 , 또는 큰 따옴표로 묶인 원시 문자열의 끝에서 \. 사용 통계는 두 문자 시퀀스를 선호하며 끝에있는 한 문자 시퀀스를 선호해야합니다.
호브

3

r'\'구문이 잘못된 이유 는 문자열식이 원시이지만 사용 된 따옴표 (싱글 또는 더블)는 항상 따옴표의 끝을 표시하기 때문에 이스케이프해야하기 때문입니다. 따라서 작은 따옴표로 묶은 문자열 안에 작은 따옴표를 표현하려면 사용하는 것 외에 다른 방법이 없습니다\' . 큰 따옴표에도 동일하게 적용됩니다.

그러나 당신은 사용할 수 있습니다 :

'\\'

4
'why'에 대답하지 않습니다 :-)
cdleary

2

그 이후에 답변을 삭제 한 다른 사용자 (신용을 원하는지 확실하지 않음)는 Python 언어 디자이너가 동일한 구문 분석 규칙을 사용하고 이스케이프 문자를 원시 형식으로 확장하여 파서 디자인을 단순화 할 수 있다고 제안했습니다. (리터럴이 원시로 표시된 경우).

나는 그것이 흥미로운 아이디어라고 생각했고 후손을위한 커뮤니티 위키로 포함시켰다.


그러나 두 개의 별도의 문자열 리터럴 파서 코드 경로가 없도록 할 수 있습니다.
cdleary

2

역활에도 불구하고 원시 문자열조차도 단일 백 슬래시로 끝날 수 없습니다. 백 슬래시는 다음 따옴표 문자를 이스케이프하기 때문에 여전히 따옴표로 묶어 문자열에 포함시켜야합니다. 즉, r "... \"는 유효한 문자열 리터럴이 아닙니다. 원시 문자열은 홀수의 백 슬래시로 끝날 수 없습니다.
단일 백 슬래시로 원시 문자열을 종료해야하는 경우 2를 사용하고 두 번째를 분리 할 수 ​​있습니다.


1

C에서 나온 것처럼 하나의 \는 이스케이프 문자로 작동하여 줄 바꿈, 탭 및 따옴표와 같은 특수 문자를 문자열에 넣을 수 있습니다.

"을 탈출하고 파서를 질식시킬 것이기 때문에 \\는 마지막 문자로 허용되지 않습니다. 그러나 이전에 지적 된 것처럼 \는 합법적입니다.


1
예, 문제의 핵심은 원시 문자열이 이스케이프 시퀀스의 시작 대신 리터럴로 취급한다는 것입니다. 이상한 점은 문자 그대로 취급되지만 인용에 대한 이스케이프 속성이 여전히 있다는 것입니다.
cdleary

1

몇 가지 팁 :

1) 경로에 대한 백 슬래시를 조작 해야하는 경우 표준 파이썬 모듈 os.path가 친구입니다. 예를 들면 다음과 같습니다.

os.path.normpath ( 'c : / 폴더 1 /')

2) 문자열의 끝에 백 슬래시가 없지만 백 슬래시가있는 문자열을 작성하려면 원시 문자열이 친구입니다 (리터럴 문자열 앞에 'r'접두사 사용). 예를 들면 다음과 같습니다.

r'\one \two \three'

3) 변수 X의 문자열 앞에 백 슬래시를 붙이려면 다음과 같이하십시오 :

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) 끝에 백 슬래시가있는 문자열을 만들어야하는 경우 팁 2와 3을 결합하십시오.

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

이제 lilypond_statement는 다음을 포함합니다 "\DisplayLilyMusic \upper"

긴 라이브 파이썬! :)

n3on


1
이 중 어느 것도 "왜"라는 질문에 대답하지 않지만 # 3과 # 4는 사용해서는 안됩니다. 문자열을 자르고 추가하는 것은 일반적으로 나쁜 습관이므로 # 3 (r '\ dummy') (# 작동)과 ''.join ([r '\ DisplayLilyMusic', r '\ upper'])-# 4를 선호해야합니다.
cdleary

1
문자열을 변경할 수없고 각 슬라이스 / 연결이 일반적으로 버려지는 새로운 불변 ​​문자열 개체를 생성하는 이유입니다. str.join (components)을 사용하여 한 번에 모두 모아서 함께 결합하는 것이
좋습니다

오, 으악-당신이 # 3의 의미를 오해했습니다. 나는 단순한 '\\'+ X가 문자열을 슬라이스하는 것보다 선호한다고 생각합니다.
cdleary

그냥 os.path.normpath뒤에서 백 슬래시를 제거 찾을 것입니다 ... 그렇다면 어떻게 파일 이름을 경로에 연결해야합니까 ...
Jing He

0

이 문제가 발생하여 일부 경우에 적합한 부분 솔루션을 찾았습니다. 파이썬은 단일 백 슬래시로 문자열을 종료 할 수 없지만, 끝에 백 슬래시가있는 텍스트 파일로 직렬화 및 저장 될 수 있습니다. 따라서 컴퓨터에 단일 백 슬래시가있는 텍스트를 저장해야하는 경우 가능합니다.

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 파이썬의 json 라이브러리를 사용하여 덤프하면 json과 함께 작동하지 않습니다.

마지막으로 Spyder와 함께 일하고 변수 탐색기에서 해당 이름을 두 번 클릭하여 거미의 텍스트 편집기에서 변수를 열면 단일 백 슬래시가 표시되고 클립 보드에 그런 식으로 복사 할 수 있음을 알았습니다. 대부분의 요구에 도움이 될 수도 있지만 일부에게는 도움이 될 수도 있습니다.).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.