SyntaxWarning: "is" with a literal. Did you mean "=="?
is 는 같은 객체인지를 보고 == 는 같은 값인지를 본다. 리터럴과 is 로 견주는 코드는 거의 언제나 == 를 의도한 것이므로 파이썬이 경고한다.
if x is 100: # 경고. 동작도 보장되지 않는다
if x == 100: # 이것이 맞다
작은 정수(-5~256) 와 짧은 문자열은 인터프리터가 객체를 재사용하기 때문에 is 가 우연히 참이 되는 경우가 있다. 범위를 벗어나면 조용히 거짓이 된다. 이 재사용은 구현 세부사항이라 버전과 실행 방식에 따라 달라지므로 기대면 안 된다.
a = 256; b = 256
a is b # True — 캐시된 같은 객체
a = 257; b = 257
a is b # False 가 될 수 있다
is 를 쓰는 것이 옳은 자리는 단일 객체(싱글턴) 와 비교할 때다.
if value is None: ...
if flag is True: ... # 진짜로 True 객체인지 가려야 할 때만
if obj is sentinel: ...
파이썬 3.12 부터 이 진단은 SyntaxWarning 으로 승격돼 기본으로 보인다. 경고를 숨기지 말고 고친다.
kinit 는 외부 명령이므로 subprocess 로 부르는 것이 가장 단순하다. 비밀번호를 인자로 넘기면 ps 에 보이므로 표준 입력으로 준다.
import subprocess
def kinit_with_password(principal: str, password: str) -> None:
p = subprocess.run(
['kinit', principal],
input=password.encode(),
capture_output=True,
)
if p.returncode != 0:
raise RuntimeError(p.stderr.decode().strip())
keytab 이 있으면 비밀번호를 다루지 않아도 된다. 서비스 계정에서는 이쪽을 쓴다.
subprocess.run(['kinit', '-kt', '/etc/security/keytabs/app.keytab', 'app@EXAMPLE.COM'], check=True)
티켓 캐시를 프로세스마다 따로 두려면 환경 변수로 지정한다. 여러 프린시펄을 동시에 쓸 때 서로 덮어쓰는 것을 막는다.
import os, tempfile
os.environ['KRB5CCNAME'] = f'FILE:{tempfile.mkdtemp()}/ccache'
외부 명령을 쓰지 않으려면 gssapi 패키지로 직접 자격증명을 얻을 수 있다. HTTP 요청에 SPNEGO 인증을 붙일 때는 requests-gssapi 를 쓴다.
import gssapi
name = gssapi.Name('app@EXAMPLE.COM', gssapi.NameType.kerberos_principal)
store = {'client_keytab': '/etc/security/keytabs/app.keytab'}
creds = gssapi.Credentials(name=name, store=store, usage='initiate')
print(creds.lifetime)
티켓은 만료되므로 장시간 도는 프로세스라면 갱신 주기를 따로 관리하거나 k5start 같은 도구에 맡긴다.