<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on 얼쑤 · Team Edo</title><link>https://team-edo.github.io/tags/python/</link><description>Recent content in Python on 얼쑤 · Team Edo</description><generator>Hugo</generator><language>ko-kr</language><lastBuildDate>Wed, 28 Oct 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://team-edo.github.io/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>FFmpeg를 유지하며 Python 3.12로 맞추기</title><link>https://team-edo.github.io/posts/2026/10/pin-managed-python-in-shared-base-image/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0900</pubDate><guid>https://team-edo.github.io/posts/2026/10/pin-managed-python-in-shared-base-image/</guid><description>&lt;p>녹음 업로드는 백엔드에서 검사하고, 채점은 Python 분석 서비스에서 실행합니다. 두 서비스에서 같은 FFmpeg 패키지를 쓰기 위해 분석 이미지의 기반을 백엔드와 같은 Ubuntu &lt;strong>26.04&lt;/strong>로 맞췄습니다. 당시 기반 이미지의 시스템 Python은 &lt;strong>3.14&lt;/strong>였고, 분석 프로젝트는 &lt;strong>3.12&lt;/strong>를 사용했습니다. Python 버전을 맞추려고 기반 이미지를 바꾸면 함께 맞춰 둔 FFmpeg 패키지부터 다시 확인해야 했습니다.&lt;/p>
&lt;h2 id="시스템-python과-프로젝트-python을-분리했다">시스템 Python과 프로젝트 Python 분리&lt;/h2>
&lt;p>이미지에 uv를 넣고 &lt;code>UV_PYTHON_PREFERENCE=only-managed&lt;/code>로 설정했습니다. 프로젝트의 &lt;code>.python-version&lt;/code>에 있는 버전을 읽어 uv가 관리하는 Python을 설치하게 했습니다. 런타임 계정도 읽을 수 있는 공용 위치에 설치하고, 앱이 시작될 때는 그 Python으로 만든 가상 환경을 사용하도록 했습니다. uv를 가져오는 이미지도 다이제스트로 지정해 빌드가 참조하는 도구의 버전을 고정했습니다. &lt;a href="https://docs.astral.sh/uv/concepts/python-versions/#adjusting-python-version-preferences">uv의 관리형 Python 설정&lt;/a>&lt;/p></description></item><item><title>빈 로그에서도 통과하는 비밀값 검사</title><link>https://team-edo.github.io/posts/2026/10/capture-isolated-python-logs/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0900</pubDate><guid>https://team-edo.github.io/posts/2026/10/capture-isolated-python-logs/</guid><description>&lt;p>얼쑤의 분석 API는 시도마다 처리 결과를 한 줄로 남깁니다. 개발 환경에 따라 루트 로거에 이미 처리기가 붙어 있을 수 있어서, 모듈 처리기에서도 같은 줄을 출력하면 기록이 두 번 나타날 수 있습니다. 모듈의 처리기는 유지하고 &lt;code>propagate = False&lt;/code>를 설정해 그 기록을 루트 쪽으로 다시 보내지 않도록 했습니다.&lt;/p>
&lt;p>이 설정을 바꾸자 테스트에서 별도의 경로를 고려해야 했습니다. pytest의 &lt;code>caplog&lt;/code>가 루트에 붙어 있는 상태에서는 이 모듈이 로그를 남겨도 캡처에 들어오지 않습니다. 검사 내용이 “서명값이 로그에 없다”뿐이면 빈 캡처에서도 통과합니다. 확인하려던 로거에 실제 이벤트가 들어오는지 먼저 확인해야 했습니다.&lt;/p></description></item><item><title>컨테이너 기동 후 첫 분석 요청이 500인 이유</title><link>https://team-edo.github.io/posts/2026/10/numba-cache-nonroot-first-request/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0900</pubDate><guid>https://team-edo.github.io/posts/2026/10/numba-cache-nonroot-first-request/</guid><description>&lt;p>얼쑤의 녹음 분석 API를 Docker 이미지로 만들었습니다. 이미지 안에서 root로 실행한 테스트는 통과했고, 기본 실행 명령으로 서버도 떴습니다. 그런데 기본 계정으로 뜬 서버에 처음 녹음 분석을 요청하자 HTTP 500이 돌아왔습니다. 로그에는 &lt;code>RuntimeError&lt;/code>가 남았습니다. 서버가 요청을 받을 수 있게 된 시점과 실제로 분석 코드를 불러오는 시점 사이에 차이가 있었습니다.&lt;/p>
&lt;h2 id="분석-코드를-불러올-때-캐시가-필요했다">모듈을 불러올 때 필요한 Numba 캐시&lt;/h2>
&lt;p>분석에 쓰는 librosa에는 Numba가 JIT 컴파일하고 결과를 캐시하는 함수가 있습니다. 이번에는 분석 요청에서 관련 모듈을 불러올 때 Numba가 캐시 위치를 찾지 못해 &lt;code>cannot cache function … no locator available&lt;/code> 오류를 냈습니다. 요청 전체를 보내지 않고 같은 이미지에서 &lt;code>import librosa.core.notation&lt;/code>만 실행해도 이 오류를 확인할 수 있었습니다.&lt;/p></description></item></channel></rss>