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の始め方についてさらに詳しい指南が欲しい場合は、Cloud Console を使用したクイックスタート を参照してください。

データ構造#

それぞれのダウンロードの情報を格納した ``bigquery-public-data.pypi.file_downloads``テーブルについての説明をLinehaulが書きました。このテーブルは、どのファイルがどのようにダウンロードされたかに関する情報を格納しています。テーブル構造 から役に立つカラムをいくつか挙げると:

カラム

説明

timestamp

日付と時刻

2020-03-09 00:33:03 UTC

file.project

プロジェクト名

pipenv, nose

file.version

パッケージのバージョン

0.1.6, 1.4.2

details.installer.name

インストーラ

pip、 bandersnatch

details.python

Pythonバージョン

2.7.12, 3.6.4

役に立つクエリ#

「クエリを新規作成」ボタンをクリックすることで 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

注意書き#

上記の背景に列挙した注意書きに加えて、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 経由でクエリ結果を参照することができます。

参考文献#