PyPIパッケージのダウンロード状況の解析#
この節では、公開のPyPIダウンロードデータセットを用いて、PyPIにホストされているパッケージ(あるいはパッケージ群)のダウンロード状況を詳しく見ていくことを記述しています。例えば、ダウンロードに使われたPythonのバージョンの分布を発見することができます。
背景#
PyPIはいくつもの理由からダウンロード統計を表示しません。:[1]
コンテンツデリバリネットワーク(CDN)と一緒に動かす時の効率の悪さ ダウンロード用系は常に変動します。プロジェクトのページでのダウンロードは強烈にキャッシュされていますが、(訳註、統計を正しく取ろうとするなら)より頻繁にキャッシュし直さなければならず、これはキャッシュの効率性を損ねます。
非常に不正確 次に挙げるものを含め、いくつもの要因でダウンロード数が正確とは言えないものになります:
``pip``のダウンロードキャッシュ (ダウンロード数を小さくする)
内部の、または、非公式のミラーサイト (ダウンロード数を大きくする要因にも小さくする要因にもなる)
PyPIにホストされていないパッケージ (比較することの妥当性を損ねる)
ダウンロード数を増やす非公式のスクリプトまたは試行 (ダウンロード数を大きくする)
過去のデータ品質における既知の問題 (ダウンロード数を小さくする)
とりわけ利用価値があるというわけではない プロジェクト(の配布物、訳註。)がたくさんダウンロードされたからといってそれだけで良いことだと決まったわけではありませんし、あまりダウンロードされなかったとしてもそれだけで悪いことだと決めつけることもできません!
まとめると、様々な理由からそれ(訳註、ダウンロード統計)の価値が低い上、動作させるために犠牲になるものが多いので、限られた資源の効率的な利用にはならないのです。
公開データセット#
別の方法としては、 Linehaulプロジェクト がダウンロードのログをPyPIから Google BigQuery [2] へ連続的に取り出して、公開のデータセットとして保管しています。
セットアップのやり方#
Google BigQuery を使って PyPIダウンロード統計の公開データセット に問い合わせを行うためには、まずGoogleアカウントが必要で、Google Cloud Platform (GCP)でBigQuery APIを有効にしておく必要があります。クレジットカード登録なしのBigQuery 無料枠 を使うと一ヶ月当たり1TBまでのクエリを走らせることができます
BigQuery ウェブ UI への道案内。
新しいプロジェクトを作成する。
BigQuery API を有効にする。
BigQueryの始め方についてさらに詳しい指南が欲しい場合は、Cloud Console を使用したクイックスタート を参照してください。
データ構造#
それぞれのダウンロードの情報を格納した ``bigquery-public-data.pypi.file_downloads``テーブルについての説明をLinehaulが書きました。このテーブルは、どのファイルがどのようにダウンロードされたかに関する情報を格納しています。テーブル構造 から役に立つカラムをいくつか挙げると:
カラム |
説明 |
例 |
---|---|---|
timestamp |
日付と時刻 |
|
file.project |
プロジェクト名 |
|
file.version |
パッケージのバージョン |
|
details.installer.name |
インストーラ |
pip、 bandersnatch |
details.python |
Pythonバージョン |
|
役に立つクエリ#
「クエリを新規作成」ボタンをクリックすることで BigQuery web UI 内でクエリを走らせましょう。
クエリのコストを削減するためにデータベースの行がパーティションされた状態で格納されていることを覚えておいてください。これらの例では、timestamp
カラムを使って絞り込むことで最近のダウンロード履歴を分析しています。
パッケージのダウンロードを数える#
次のクエリは"pytest"プロジェクトのダウンロード総数を数えています。
#standardSQL
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
-- Only query the last 30 days of history
AND DATE(timestamp)
BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND CURRENT_DATE()
num_downloads |
---|
26190085 |
pipを通じてダウンロードされた数だけを数えるには、``details.installer.name``カラムを使って抽出してください。
#standardSQL
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
AND details.installer.name = 'pip'
-- Only query the last 30 days of history
AND DATE(timestamp)
BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND CURRENT_DATE()
num_downloads |
---|
24334215 |
時系列のパッケージダウンロード数#
月毎のダウンロード数を数えるには、``TIMESTAMP_TRUNC``関数を使います。このカラムを使って抽出することは、通信量を抑えることにもなります。
#standardSQL
SELECT
COUNT(*) AS num_downloads,
DATE_TRUNC(DATE(timestamp), MONTH) AS `month`
FROM `bigquery-public-data.pypi.file_downloads`
WHERE
file.project = 'pytest'
-- Only query the last 6 months of history
AND DATE(timestamp)
BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH)
AND CURRENT_DATE()
GROUP BY `month`
ORDER BY `month` DESC
num_downloads |
month |
---|---|
1956741 |
2018-01-01 |
2344692 |
2017-12-01 |
1730398 |
2017-11-01 |
2047310 |
2017-10-01 |
1744443 |
2017-09-01 |
1916952 |
2017-08-01 |
時系列で見たPythonバージョン#
``details.python``カラムからPythonのバージョンを取り出します。警告:このクエリは500GB以上のデータを処理します。
#standardSQL
SELECT
REGEXP_EXTRACT(details.python, r"[0-9]+\.[0-9]+") AS python_version,
COUNT(*) AS num_downloads,
FROM `bigquery-public-data.pypi.file_downloads`
WHERE
-- Only query the last 6 months of history
DATE(timestamp)
BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH)
AND CURRENT_DATE()
GROUP BY `python_version`
ORDER BY `num_downloads` DESC
python |
num_downloads |
---|---|
3.7 |
18051328726 |
3.6 |
9635067203 |
3.8 |
7781904681 |
2.7 |
6381252241 |
null |
2026630299 |
3.5 |
1894153540 |
アーティファクトへの完全なリンクを得る#
例えばあるプロジェクトやリリースが PyPI から削除されてしまったような場合に、ハッシュ値に基づいて PyPI からアーティファクト(訳注、そのようなプロジェクトやリリース)をダウンロードすることができる完全なリンクがあれば便利な時もあるでしょう。メタデータテーブルには path
列があって、ハッシュ値とアーティファクトのファイル名を保持しています。
注釈
ここで生成された URL はいつまでも存在するとは限りませんが、しかし、その時点で PyPI のアーティファクトがどこに保存されているかを示す URL を含んでいます。
SELECT
CONCAT('https://files.pythonhosted.org/packages', path) as url
FROM
`bigquery-public-data.pypi.distribution_metadata`
WHERE
filename LIKE 'sampleproject%'
url |
---|
注意書き#
上記の背景に列挙した注意書きに加えて、Linehaulは、極端に過小報告されていたダウンロード統計の原因となったバグに2018年7月26日まで悩まされていました。この日より前のダウンロード数については、比率の点(例えばPython2とPython3の百分率)では正確ですが、絶対数の点では桁が異なるほどに過小です。
その他のツール#
BigQueryコンソールを用いる他に、ダウンロード統計を分析する際に役に立つと思われるツールがいくつかあります。
google-cloud-bigquery
#
BigQuery APIとBigQuery用の公式Pythonクライアントである google-cloud-bigquery プロジェクトを使って、プログラムからPyPIの公開ダウンロード統計データセットにアクセスすることもできます。
from google.cloud import bigquery
# Note: depending on where this code is being run, you may require
# additional authentication. See:
# https://cloud.google.com/bigquery/docs/authentication/
client = bigquery.Client()
query_job = client.query("""
SELECT COUNT(*) AS num_downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'pytest'
-- Only query the last 30 days of history
AND DATE(timestamp)
BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND CURRENT_DATE()""")
results = query_job.result() # Waits for job to complete.
for row in results:
print("{} downloads".format(row.num_downloads))
pypinfo
#
pypinfo はデータセットにアクセスして、役に立つクエリをいくつか生成する機能を提供するコマンドラインツールです。例えば、``pypinfo package_name``を実行すれば、そのパッケージのダウンロード総数を問い合わせることができます。
pipを用いて pypinfo をインストール。
python3 -m pip install pypinfo
使い方:
$ pypinfo requests
Served from cache: False
Data processed: 6.87 GiB
Data billed: 6.87 GiB
Estimated cost: $0.04
| download_count |
| -------------- |
| 9,316,415 |
pandas-gbq
#
pandas-bbq プロジェクトを使えば Pandas 経由でクエリ結果を参照することができます。