Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Python packaging

1,147 views

Published on

Published in: Technology
  • Be the first to comment

Python packaging

  1. 1. Python PackagingThe Architecture of Open Source Applications 2012-11-17 아꿈사 김지훈
  2. 2. 제품의 인스톨 방법Standalone Package윈도우 방식 리눅스 방식필요한건 스스로 조달 Repository에서 조달설치가 간편 배포가 간편실행이 안정적임 유지관리가 용이
  3. 3. 제품의 인스톨 방법Standalone Package윈도우 방식 리눅스 방식필요한건 스스로 조달 Repository에서 조달설치가 간편 배포가 간편실행이 안정적임 유지관리가 용이 Python 표준
  4. 4. 이상적인 패키징 시스템플랫폼 독립적다시 패키징 하는 것이 가능한가?시스템 의존성이 명확해야함
  5. 5. 비표준 패키징 시스템의 문제점알 수 없는 버전 넘버링 Fumanchu가 먼저인가 Phill이 먼저인가?관례를 깨는 시스템 자원 사용 로컬 디렉토리에 쓰기 권한이 없다면?관리자도 시스템에 뭐가 있는지 모른다.
  6. 6. Python의 패키징 시스템들 Standard Library Distribute Distutils Setuptools Pip
  7. 7. Python의 패키징 시스템들 Standard Library Distribute Distutils Setuptools Pip
  8. 8. Distutils의 설계오류
  9. 9. setup.py내가 작성한 mycode.py를 배포하고 싶다면from distutils.core import setupsetup(name=MyProject, version=1.0, py_modules=[mycode.py])
  10. 10. setup.py의 문제점 All In One
  11. 11. setup.py의 문제점setup.py파일은 간단한 문자열 하나를 얻기 위해 많은 작업을 수행일부 개발자들은 setup.py가 오직 인스톨 용도이거나, 또는 개발하는 동안만 쓸 목적일 수 도 있음.$ python setup.py --nameBuilding lxml version 2.2.NOTE: Trying to build without Cython, pre-generated src/lxml/lxml.etree.cneeds to be available.Using build configuration of libxslt 1.1.26Building against libxml2/libxslt in the following directory: /usr/lib/lxml
  12. 12. PyPIThe Python Package Index파이썬 패키지들의 리파지토리
  13. 13. PyPI 메타데이터 Name 프로젝트 이름 Version 릴리즈 버전 Summary 한 줄짜리 설명 Description 세부 설명 Home-Page 프로젝트 URL Author 제작자 이름 Classifiers 프로젝트 구분자 Requires, Provides, Obsoletes 모듈들과의 의존성을 정의
  14. 14. 의존성 정의from distutils.core import setupsetup(name=foo, version=1.0, requires=[ldap])
  15. 15. 의존성 정의from distutils.core import setupsetup(name=foo, version=1.0, requires=[ldap])ldap이라는 모듈이 없다면?어느 패키지의 ldap인가?
  16. 16. 의존성 정의from distutils.core import setupsetup(name=foo, version=1.0, requires=[win32com])
  17. 17. 의존성 정의from distutils.core import setupsetup(name=foo, version=1.0, requires=[win32com])리눅스에 설치한다면??
  18. 18. 의존성 정의from distutils.core import setupimport sysif sys.platform == win32: setup(name=foo, version=1.0, requires=[win32com])else: setup(name=foo, version=1.0)
  19. 19. 의존성 정의from distutils.core import setupimport sysif sys.platform == win32: setup(name=foo, version=1.0, requires=[win32com])else: setup(name=foo, version=1.0)클라이언트에서 컴파일을 해봐야만 알 수 있다.윈도우에 의존적임을 PyPI에 알려줄 방법이 없음
  20. 20. 언인스톨이 되지 않음설치한 파일에 대한 히스토리를 남기지 않음--record 옵션은 기본 값이 아님
  21. 21. PyPI의 한계
  22. 22. 프로젝트 등록$ python setup.py registerrunning registerRegistering MPTools to http://pypi.python.org/pypiServer response (200): OK
  23. 23. 프로젝트 업로드$ python setup.py sdist uploadrunning sdist…running uploadSubmitting dist/mopytools-0.1.tar.gz to http://pypi.python.org/pypiServer response (200): OK
  24. 24. The Simple Index Protocol인스톨러에게 프로젝트의 링크를 제공http://pypi.python.org/simple/
  25. 25. XML RPC Method프로젝트의 상세한 메타데이터 제공# python 3.x sample codeimport xmlrpc.clientimport pprintpypi = xmlrpc.client.ServerProxy(http://pypi.python.org/pypi)pypi.package_releases(an_example_pypi_project)pprint.pprint(pypi.release_urls(an_example_pypi_project, 0.0.5))pprint.pprint(pypi.release_data(an_example_pypi_project, 0.0.5))
  26. 26. 문제점PyPI 서버 부하 Single point of failure프로젝트 url의 간접적인 참조분산되어 있는 프로젝트 메타데이터
  27. 27. 문제 해결을 위한 노력들
  28. 28. Setuptools프로젝트 수준의 의존성 지원easy_install 스크립트 지원 PyPI를 참조하여 자동으로 의존성 설정문제점 더 많은 PyPI 부하 롤백이 지원되지 않음
  29. 29. Pip언인스톨러 제공 새로운 메타파일 제공다양한 종류의 설치 메타파일이 혼재 Distutils Setuptools Pip 그외 다른 패키징시스템
  30. 30. 데이터파일 문제setup(…, data_files=[(bitmaps, [bm/b1.gif, bm/b2.gif]), (config, [cfg/data.cfg]), (/etc/init.d, [init-script])] )설치 경로가 setup.py에 하드코딩 되어있음
  31. 31. 데이터파일 문제리패키징하기위해서는 setup.py를 분석해야한다사용자가 데이터파일의 위치를 결정할 수 없다데이터파일의 분류가 없다
  32. 32. 데이터파일 문제리패키징하기위해서는 setup.py를 분석해야한다사용자가 데이터파일의 위치를 결정할 수 없다데이터파일의 분류가 없다이러한 문제를 Setuptools와 Pip는 개선하지 않음
  33. 33. 새로운 표준
  34. 34. 버전N.N[.N]+[{a|b|c|rc}N[.N]+][.postN][.devN]PEP 386 N은 정수 a, b, c, rc 는 알파, 베타, 릴리즈 후보 dev 다음엔 숫자가 따라옴 post-release는 post다음에 숫자가 따라옴이 규칙을 따르지 않는 프로젝트는 PyPI에 업로드 거부
  35. 35. 의존성Requires-DistRequires-Dist: pkginfoRequires-Dist: PasteDeployRequires-Dist: zope.interface (>3.5.0)Provies-DistProvides-Dist: transactionObsoletes-DistObsoletes-Dist: OldName여러번 반복하여 선언 가능
  36. 36. 실행환경 정의메타데이터에 플랫폼 의존성 정의Requires-Dist: pywin32 (>1.0); sys.platform == win32Obsoletes-Dist: pywin31; sys.platform == win32Requires-Dist: foo (1,!=1.3); platform.machine == i386Requires-Dist: bar; python_version == 2.4 or python_version == 2.5Requires-External: libxslt; linux in sys.platform
  37. 37. 설치 포맷여러 패키징 툴 간의 호환성을 위한 표준METADATA 메타데이터 기술RECORD 설치한 파일 목록INSTALLER 설치한 툴 이름REQUESTED 직접 설치한건지 여부패키징 툴에 독립적으로 프로젝트 관리
  38. 38. 데이터 파일 구조import oshere = os.path.dirname(__file__)cfg = open(os.path.join(here, config, mopy.cfg))
  39. 39. 데이터 파일 구조import oshere = os.path.dirname(__file__)cfg = open(os.path.join(here, config, mopy.cfg))import osimport pkgutil# Open the file located in config/mopy.cfg in the MPTools projectcfg = pkgutil.open(MPTools, config/mopy.cfg)
  40. 40. 데이터 파일 구조import oshere = os.path.dirname(__file__)cfg = open(os.path.join(here, config, mopy.cfg))import osimport pkgutil# Open the file located in config/mopy.cfg in the MPTools projectcfg = pkgutil.open(MPTools, config/mopy.cfg)RESOURCES config/mopy.cfg {confdir}/{distribution.name}
  41. 41. Distutils2Setup.py는 더 이상 사용하지 않음.setup.cfg에 ini파일 형식으로 메타데이터 기록Python 3.3에 Packaging이란 이름으로 포함 예정??
  42. 42. setup.cfg[metadata]name = MPToolsversion = 0.1author = Tarek Ziadeauthor-email = tarek@mozilla.comsummary = Set of tools to build Mozilla Services appsdescription-file = READMEhome-page = http://bitbucket.org/tarek/pypi2rpmproject-url: Repository, http://hg.mozilla.org/services/server-devtoolsclassifier = Development Status :: 3 - Alpha License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)
  43. 43. setup.cfg[files]packages = mopytools mopytools.testsextra_files = setup.py README build.py _build.pyresources = etc/mopytools.cfg {confdir}/mopytools
  44. 44. PyPI의 개선
  45. 45. 미러링 서버 구성호스트 이름 X.pypi.python.org X는 a, b, c, …, aa, ab, …의 시퀀스 last.pypi.python.org : 마지막 미러 서버>>> import socket>>> socket.gethostbyname_ex(last.pypi.python.org)[0]g.pypi.python.org>>>
  46. 46. 미러링 서버 구성동기화 변경된 패키지만 동기화 /simple /packages통계 전파 다운로드 횟수 마스터 서버에서 stats디렉토리에 방문하여 수집
  47. 47. 보안 위협중앙 인덱스 서버가 탈취되었을 가능성미러가 조작되었을 가능성중간자 공격(Man in the Middle Attack)
  48. 48. 패키지 검증1. /simple 페이지를 다운로드하여 SHA-1 해시를 계산한다.2. 해당 해시의 DSA 시그니처를 계산한다.3. /serversig 와 일치하는 것을 다운로드하여 2단계에서 계산된 것 과 바이트 단위로 비교한다.4. 미러서버에서 다운로드한 모든 파일에 대한 MD5 해시를 계산하 고 검증한다.
  49. 49. 교훈
  50. 50. 제대로 PEP 프로세스를 밟아야 한다Setuptools는 별다른 PEP의 수정없이 메타데이터를 확장문제 해결을 위한 노력이 더 큰 문제를 유발Setuptools는 좋은 테스트 케이스였음
  51. 51. 표준 라이브러리의 패키지는 오래 못간다표준라이브러리의 수정은 매우 어렵다한 번 공개된 API는 수 년간 유지 됨중요한 수정이 필요할땐 새로운 패키지를 만든다
  52. 52. 하위 호환성기존의 프로젝트들이 Distutils2를 사용하게 되기까진 수 년이 걸릴 것임따라서 하위호환성 유지는 필연적
  53. 53. Referencehttp://www.aosabook.org/en/packaging.html

×