2016年9月21日
パッケージングを支える技術
PyCon JP 2016
Atsushi Odagiri
1 お前だれよ
• 小田切篤
• Beproud, Inc.
2 これまでのお話
• 2013 パッケージングの今と未来
• 2014 パッケージングの今
• 2015 Packaging最前線
3 アジェンダ
• パッケージングを支えるツール
• ソースパッケージ
• バイナリパッケージ
• パッケージングを支える技術に支えられてみ
よう
4 パッケージングを支える
ツール
• PyPA ってなに?
4.1 PyPA
• Python Packaging Authority
• パッケージングツールをメンテするグループ
• github.com/pypa
• bitbucket.org/pypa
4.2 PyPAの基本ツール
• setuptools
• virtualenv
• pip
• wheel
4.3 setuptools
• 配布物を作成する
• setup.pyで使われる
• easy_install使うのはもうやめましょう
• distributeも、いい加減忘れてください
• egg? あれは幻です
4.4 今日のsetuptools
• 27.2.0
• 去年(2016/9/6)18.3
4.5 virtualenv
• python環境を仮想化する
• プロジェクトごとに使うライブラリを隔離
• python3.3以降では同等の機能がpython本体か
ら提供されている(pyvenv)
4.6 pip
• インストーラ
• sdistとwheelを取り扱える
• requirements.txt でライブラリを構成管理する
4.7 wheel
• wheel形式パッケージを作成するツール
• setuptools に bdist_wheel サブコマンドを追
加する
4.8 ツールの導入方法
• python3.4以降ではpip,setuptoolsを導入する
ensurepipが入っているのでpythonインストー
ル後にpipを利用可能
• virtualenvは環境作成時にpip,setuptools,wheel
を導入する
• pyvenvはバージョンによって作成後のツール
導入が異なる
– 3.3 なし
– 3.4以降 ensurepipでpip,setuptoolsが導入さ
れる
• どの環境でもget-pip.py で
pip,setuptools,wheelを最新にできる
4.9 例えばubuntuのpyvenv
• 14.04 の python3.4 は ensurepipが消されてい
るため、–without-pipをつけないとエラーに
なる
• 16.04 の python3.5はensurepipが
pkg_resources-0.0.0という謎のパッケージメ
タデータを作成する
– そのままpip freezeしたrequirements.txtを
作ると他の環境でエラーになる
• 回避策は –without-pip で環境を作ってから
get-pip.py でツールを導入する
5 python標準の仕組み
• pypaツールはどのようにパッケージをインス
トールしてpythonインタプリタに認識させる
のか?
5.1 PYTHONPATHとsys.path
• 環境変数PYTHON_PATHで複数のディレク
トリを指定できる
• 指定した内容は ‘sys.path‘ に入る
• モジュールやパッケージを ‘import‘ するとき
は ‘sys.path‘ のディレクトリを探しに行く
• よくわからないところにインストールしても
sys.path に追加できればよい
5.2 site-packages/user-site-packages
• サードパーティ製ライブラリの標準インストー
ル先
• debianではさらに dist-packages という謎の
ディレクトリが存在する
• user-site-packages はユーザー権限でインス
トールできる
• user-site-packages にインストールするには
pipで ‘–user‘ オプションを使う
5.3 .pth
• site-packages などに配置されるファイル
• 中にファイルパスを羅列しておくと、インタプ
リタ起動時にすべて ‘sys.path‘ に追加される
• ‘./‘ 以外で始まる行があるとpythonコードとし
て実行されるという謎仕様
• easy_install が活用していた
5.4 distutils
• setup.py で使う setup 関数の大元
• setuptoolsはdistutilsの拡張
• 直接使うことはもうないはず
• 昔はこれで setup.py install などとしていた
6 バイナリディストリビュー
ション wheel
• wheelもう使ってるよね?
6.1 PEP 427 – The Wheel Binary
Package Format 1.0
• バイナリ形式の配布フォーマット
• 既に利用されている
• C拡張を含まない場合はpy2.py3で共通の配
布物
6.2 PEP 513 – A Platform Tag for
Portable Linux Built Distributions
• これまではLinux向けwheelはpypiにあげられ
なかった
• manylinux1
• linux向けのwheelを作るために決められた
6.3 Linux向けwheelパッケージのつら
いところ
• どのようなライブラリがあると想定してよ
いか?
• 依存するライブラリのABIが合わないなどのト
ラブル
• 依存ライブラリ同梱のためのハックがsetup.py
に散らばる
6.4 Python の ABI
• pymalloc
• ucs-4
• python3ではすべてucs-4ビルド
6.5 wheelの名前規約からわかること
• numpy-1.11.2rc1-
cp35-cp35m-manylinux1_x86_64.whl
– numpy という名前のパッケージ
– 1.11.2rc1 というバージョン
– CPython 3.5 のAPI
– CPython pymallocビルドのABI
– manylinux1_x86_64 プラットフォーム
6.6 manylinux1が想定するLinux環境
• Centos5.11相当
• x86とx86_64の両方
• その他前提としてよいライブラリ
6.7 manylinux1でインストールを期待
してよいライブラリ(1)
• libpanelw.so.5
• libncursesw.so.5
• libgcc_s.so.1
• libstdc++.so.6
• libm.so.6
• libdl.so.2
• librt.so.1
• libcrypt.so.1
• libc.so.6
• libnsl.so.1
6.8 manylinux1でインストールを期待
してよいライブラリ(2)
• libutil.so.1
• libpthread.so.0
• libX11.so.6
• libXext.so.6
• libXrender.so.1
• libICE.so.6
• libSM.so.6
• libGL.so.1
• libgobject-2.0.so.0
• libgthread-2.0.so.0
• libglib-2.0.so.0
6.9 auditwheel
• linux向けwheelをmanylinux1に変換する
ツール
• manylinux1を満たしているかチェック
• 依存ライブラリをwheelに同梱させる
• wheelファイル名のplatform tagをmanylinux1
に変更
6.10 dockerを利用してパッケージを作
成する
• docker イメージが用意されている
– quay.io/reposi-
tory/pypa/manylinux1_x86_64
• CIでこのイメージを利用してパッケージング
する
– werckerやgitlabでは直接dockerイメージを
利用できる
– travisなどでもCIのワークフロー中にdocker
イメージを利用できる
6.11 werckerでやってみよう
box:
id: quay.io/pypa/manylinux1_x86_64
registry: quay.io
build:
steps:
- script:
name: build
code: |
/opt/python/cp35-cp35m/bin/pytho
- script:
name: test
code: |
/opt/python/cp35-cp35m/bin/pytho
- script:
name: pack
code: |
/opt/python/cp35-cp35m/bin/pytho
- script:
name: audit
code: |
auditwheel repair dist/*.whl -w
7 ソースディストリビューショ
ン sdistとはなにか?
• setuptoolsとpipの実装でなんとなく決まって
いる
• ‘setup.py install‘ ができればsdist?
7.1 setuptoolsがなくてもwheelパッ
ケージは作成できる
• wheelツールはsetuptoolsと独立して作られて
いる
• distlibにもwheelを作成する処理が実装されて
いる
7.2 sdistを考え直す意味
• setuptools依存からの脱却
• 明確なインストールフロー
7.3 現状のインストール手順
• pipがsdistをダウンロードする
• pipがsdistを展開する
• pipがsetup.py bdist_wheelを実行する
• できあがったwheelパッケージをpipがインス
トールする
• setup.py install は関係なかった
7.4 PEP 518 – Specifying Minimum
Build System Requirements for
Python Projects
• パッケージング方法やそれに必要なツールを支
持する
• pypi上でwheel作成する目的?
• パッケージングに必要なツールを記述
• pyproject.toml
• TOMLフォーマット
7.5 pyproject.toml
[build-system]
requires = ["setuptools", "wheel"]
7.6 PEP 516 – Build system abstraction
for pip/conda etc
• ビルドツールの指定や依存性を記述する
• 指定のツールでどのようにビルドするのかも
指定
• pypi.jsonというファイルで話が進んでいるっ
ぽい
• でも多分pyproject.tomの tool セクションが同
じものを指しているはず
8 プログラミングPythonパッ
ケージ
• setuptoolsに依存せずにパッケージングしてみ
よう
8.1 distlibでできること
• wheelパッケージ作成
• wheelパッケージインストール
• メタデータ作成
• パッケージリポジトリからのダウンロード
• インストール済パッケージのリストアップ
8.2 bib - reversed pip
• distlibと標準ライブラリのみで実行するパッ
ケージングツール
• 本日作成しました
8.3 distlibを使う準備
>>> import sys
>>> import os
>>> sys.path.append(
... os.path.join(
... os.getcwd(),
... ’distlib-0.2.3-py3-none-any.wh
>>> import distlib
>>> distlib
9 プロジェクトの作成
• bib.init_project
9.1 パッケージメタデータ
• dist-info ディレクトリ
• pydist.json/package.json
10 パッケージの作成
10.1 wheelパッケージを作成する
• 作業ディレクトリを作成
• パッケージ名.dist-info ディレクトリを作成
• dist-info ディレクトリ以下に pydist.json をコ
ピー
• インストール対象を作業ディレクトリにコピー
• distlib.wheelでWheelを作成する
11 パッケージの配布
• 作成したパッケージを公開してインストール可
能にする
• simple package repository形式のサイトで公開
する
• ダウンロードしてインストールする
11.1 PEP 503 – Simple Repository API
• pypiもこの形式
• 登録やアップロード方法は決められてない
• ‘httplib.server‘ などでも実現可能
11.2 wheelファイルをsimple package
repository形式に配置する
• distlib.wheelでメタデータを取得
• パッケージ名でディレクトリを作成
• wheelファイルをコピー
• そのディレクトリを対象に ‘httplib.server‘ を
立ち上げる
12 インストール
• パッケージをリポジトリからダウンロード
• パッケージのメタデータを読み取る
• Wheelで読み取って、対象ディレクトリにイン
ストール
12.1 パッケージをリポジトリからダウ
ンロードする
• distlib.locators
• SimpleScrapingLocator
• result.download_urls でURLを取得
• 一時ディレクトリに保存
12.2 wheelパッケージをインストール
する
• distlib.scripts ScriptMakerを作成
• distlib.wheelの install メソッドでインストール
12.3 インストール一覧
• PEP 376 – Database of Installed Python
Distributions
• パッケージによってインストールされたファイ
ルの情報
• どのモジュールがどのパッケージでインストー
ルされたか
• インストール時のファイルのハッシュ
• distlib.database
13 まとめ
• setuptoolsやpipがなくてもパッケージングは
できる
• いろんなツールがエコシステムに参加できるよ
うにsdistの定義が検討されている
• wheelはがんがん使いましょう

パッケージングを支える技術 pyconjp2016