Python pipenv で pywin32 をインストールするとエラー

11/10 頃から、 Python でpypiwin32 や pywin32 パッケージや、それらに依存しているパッケージを pipenv にてインストールしようとすると、

AttributeError: module 'site' has no attribute 'getsitepackages'

とエラーが出て失敗するようになった。

10/22 追記: pywin32 v227 で問題は修正された。
"there's nothing wrong with PyWin32, it's just a fix applied on PyWin32's side to work around a VirtualEnv bug." と、修正コメントで強調されている。 わかるよ、その気持ち。
追記ここまで

原因

直接的な原因は、 pipenv ではなく virtualenv にある。

続きを読む

プロキシ環境下で Ansible AWX をインストールする Playbook を作る

構成管理ツール (いわゆる Infrastructure as Code(IaC)) の中でも比較的易しいと言われる Ansible。
その Ansible の運用を省力化してくれるツールとして Ansible Tower というものがあり、そのコミュニティ管理版 (OSS版) が AWX だ。

その AWX がインストールされたサーバを作成する Playbook を作ろうとしたら意外と手間取ったので、そのメモ。

なお、インストール先は CentOS 7 である。
AWX のインストールは、 公式ビルド済み docker イメージを Docker Compose を使ってコンテナ化する方法 を使った。

11/21: 追記

docker-compose の PyPI (pip) パッケージが 1.25.0 に更新後、 CentOS 7 (正確には、 Python 2 系を使っている環境) で docker-compose のインストールや実行がうまくいかなくなった。
(commit:719a1b0 で) subprocess32 に依存するようになり、 gcc 等のビルド環境のインストールが別途必要になったためだ。

それに加え、たとえ gcc をインストールしても、依存パッケージの python2 対応が不十分なようで、 docker-compose 実行時にエラーになってしまう。

docker/compose#7030 の Issue には挙がっているが、修正されるかどうか不明なため、一つ前の 1.24.1 を使うことで回避するように、コードを修正した。

python2 ツラい。。。
しかし、 2020年にサポート切れになった後も、 CentOS 7 が生きているしばらくの間はこの辛みと付き合わなければならないようだ。
ツラい。。。

追記ここまで

最終的な Playbook

続きを読む

Pydroid で オフライン&セルフホスト の Web アプリを動かす

運用時にネットワークにつながっていない Android タブレットで、 自作のアプリケーションを 簡単に 動かすには、どうしたらよいだろうか?

.apk ビルドしてインストールさせる?いやいや、手軽からはほど遠いだろう。

現在のトレンドは PWA で Service Worker を組み合わせてキャッシュさせる方法だろうか。
PWA 配信するには https のホスティングを用意しなくてはならないし、ブラウザのキャッシュ整理したらデータが吹き飛んでしまう。

ここで私は、 Android 上で Python を動かしてセルフホストさせる方法 を提唱したい。

続きを読む

Flask + jinja でレイアウトの指定 (extends タグ) のテンプレートを ソースコード文字列 で指定する

Python の軽量な Webアプリケーション フレームワーク として有名な Flask。
この Flask を使うと たった一ひとつのソースファイルで簡単に Webアプリケーション を作成できる。

Flask では Jinja2 というテンプレートエンジンを採用している。
通常はテンプレートソースを .html ファイルにテンプレートソースを書き出して ファイル名を指定してそのテンプレートを読み出すのだが、 flask.render_template_string を使えば Python ソースコード上で定義した テンプレート文字列 を使うことができる。

しかし、 extends ステートメントや include ステートメントを使ってレイアウト用などのテンプレートを呼び出す際に、 そのテンプレートを ファイル名 で指定する方法の情報しか出てこない。
これでは、 ひとつのソースファイルで記述できない。
テンプレートソース文字列 を使ってテンプレートの継承を行う方法を、メモがてらまとめておく。

以下のサンプルは Flask を使ったものだが、 Django で Jinja2 を使用した場合も同じように対応できると思われる。


サンプル実装

extends タグinclude ステートメント では、 与えられた文字列のテンプレートファイルをテンプレートローダーが探し出して、 テンプレートの継承関係を解決する仕組みになっている。
Jinja のドキュメントには書かれていないが、 文字列ではなく Jinja の Template オブジェクト を与えると、そのテンプレートをそのまま使ってくれるようだ。

つまり、 あらかじめ Template オブジェクトを作成しておいて、 それを jinja_env.globalsrender_template_string のキーワード引数によってテンプレート内の引数に渡し、 最終的に extends タグに渡るようにすればよいのだ。

サンプルコードは以下の通り。

続きを読む

Selenium でページ全体のスクリーンショットを撮る (Python)

02/25 更新: Chrome で水平スクロールバーがスクリーンショットに写ってしまう問題を修正。

Selenium を使って自動テストを行っていると、表示された結果のスクリーンショットを撮って保存したい時がままある。

ところが、 Chrome や Firefox で Selenium のスクリーンショット機能を使うと、 ウィンドウに表示されている内容だけしか取得できない。
(ブラウザやそのバージョンによって動作が異なる)


この記事によると、これは Selenium の仕様らしい。

ブラウザごとの挙動の差はさておき、 ウィンドウサイズでの取得となってしまう Chrome と Firefox で、何とかページ全体のスクリーンショットを保存したい。
ここでは、 Selenium の Python Binding を使って、実現する方法を考えてみる。

続きを読む

pipenv の仮想環境のフォルダ名のルール

Python におけるパッケージ管理と言えば、 以前は virtualenv/venv で仮想環境を作成し、 pip を使って その仮想環境にパッケージをインストールするのが、おなじみの方法だった。

node.js の npm や .NET の dotnet restore などに慣れている人々にとっては、 環境の管理やパッケージの管理が別々だったり、 ひとつのファイル+ひとつのコマンド で環境を復元できないのは、 ソースコード管理がスマートにできず、非常に面倒に感じる。

このため、 Python にも 仮想環境・パッケージ管理を統合するツールがいくつも生まれては消えていった。
そして、最近になってついに、 Python.org 公式が推奨する Python パッケージ管理ツールとして、 pipenv というものが登場したようだ。 (→ Python.org)

pipenv の仮想環境の場所

pipenv install コマンドを使ってパッケージをインストールすると、 npm の package.json にあたる Pipfile というファイルがカレントディレクトリにできあがるが、 npm の node_modules にあたるようなパッケージがインストールされた仮想環境のフォルダは、カレントディレクトリは(標準の設定だと)作成されない。
(なお、 環境変数 PIPENV_VENV_IN_PROJECT に何らかの値を設定した場合は、 カレントディレクトリの ./.venv/ ディレクトリが仮想環境のフォルダになる。)

その仮想環境のフォルダの場所は pipenv --venv コマンドで調べることができる。
Windows の場合は、 %USERPROFILE%/.virtualenvs/ に、環境毎のサブディレクトリが作成されているはずだ。

その仮想環境ディレクトリの名前の前半は、 Pipfile が存在するフォルダの名前になるが、 最後の9文字はなにやらランダムのような名前がつけられている。
例えば、 D:/pipenv/ で pipenv を初期化した場合、 %USERPROFILE%/.virtualenvs/pipenv-LAdtM08T/ が作成されるだろう。

はたして、この文字は何なのか?

続きを読む

Python の類似画像ライブラリ ImageHash を Windows で使う

sha1 や md5 等で知られるファイルハッシュは、ファイルの1ビットでも異なると、全く別のダイジェスト値を返すように作られている。

一方で、 画像の情報をハッシュ化する際に、 画像の大きさや微妙な違いには目を瞑って同じような画像は同じダイジェスト値、似たような画像は似たようなダイジェスト値を得たい場合もある。
例えば、大きさの違う画像や、 jpeg, png の形式が異なる画像を 同じ画像として扱うようにしたい場合だ。

そのようなハッシュ関数はいくつか知られている。

  • average hashing (aHash)
  • perception hashing (pHash)
  • difference hashing (dHash)
  • wavelet hashing (wHash)

そのうち、上記の 4つ の計算を行えるのが、 Python の ImageHash ライブラリだ。

このライブラリ自体は ピュアな Python ライブラリなのだが、 依存しているパッケージが総じて C言語拡張モジュールなので Windows で動作させるにはすこし手間がかかる。

そこで、 cygwin 上の python にインストールする場合と、 Windows 上の CPython にインストールする方法をそれぞれ紹介しよう。

以下は virtualenv を使って仮想環境上にインストールする手順とするが、 直接 Python のシステム環境に入れてしまっても問題はない。

メモ: 2017年現在、 pypi でプリコンパイル済みの依存モジュールがダウンロードできるので、以下の方法を使わなくても pippipenv コマンドだけでインストールが完了するはずだ。

cygwin を使う場合

続きを読む