文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

pythonのpipでnpmのnode_modulesのようにローカルインストールして実行する

少しトリッキーなので、忘れない内に手順をまとめておきます〜

f:id:treeapps:20180424130724p:plain

サーバ上でpythonのpipでインストールしたモジュールを動かしたいのだけれど、なんとグローバルのpip installが禁止されている・・・!!というかそもそも権限が与えられなくてインストールができない・・・!!!

等という地獄の環境の場合、npmのように、ローカルインストールできれば簡単に解決するのに、と思いますよね。pythonでも可能なのですが、知ってないと中々できるものではないので、まとめておきます。

環境

  • pythonがインストール済みである。
  • pipがインストール済みである。

バージョンを問わず、上記がインストールされている事が前提になります。

ローカルインストールって?

普通に「pip install fabric」などとすると、以下のような全アカウント共通で使用する、所謂グローバルな場所にインストールされてしまいます。

/Library/Python/2.7/site-packages
/Library/Python/2.6/site-packages

やりたいのは↑ではなく、pythonのディレクトリに依存しない、自由な場所にsite-packagesを配置したいのです。

という事で早速やっていきましょう。

ローカルインストール手順

pip installに「-t」オプションを付けてインストールする

ここではfabricをインストールしてみます。

pip install -t site-packages fabric

site-packagesというフォルダ名は別の名前でもいいのですが、ここはnpmで言うところのnode_modulesに相当するので、素直にsite-packagesとした方が全員に通じる名称になると思います。

実行する.pyを用意する

なんでもいいのですが、今回はfabricを例としてい挙げたので、fabricを実行するものを用意してみます。以下を「fabfile.py」として保存します。

#coding:utf-8
from fabric import task
import shlex, subprocess

@task
def task1(c):
  subprocess.Popen("hostname")

.pyを実行する.shを用意する

pythonを直接実行するのではなく、シェルスクリプトを経由して実行します。

その際に特定の環境変数と、PATHにバイナリへのパスを追加する事で、pipのコマンドを実行する事が可能になります。以下を「run.sh」として保存します。

#!/bin/sh
currentDir=$(echo $(cd $(dirname $0) && pwd))
PYTHON_SITE_PACKAGES=${currentDir}/site-packages

# site-packagesの位置を一時的に変更する
export PYTHONPATH=$PYTHONPATH:${PYTHON_SITE_PACKAGES}
# pipでローカルインストールしたバイナリへのパスを通す
export PATH=${PYTHON_SITE_PACKAGES}/bin:$PATH
# ↑でパスを通したのでsite-packages/bin配下のバイナリが実行できるようになる
fab task1

これでローカルにインストールしたfabricのfabコマンドを実行する事が可能になります。

最終的なディレクトリ構成

tree:test tree$ tree . -L 2
.
├── fabfile.py
├── run.sh
└── site-packages
    ├── PyNaCl-1.3.0.dist-info
  ・・・略・・・
    ├── bin
  ・・・略・・・
    └── six.pyc

バイナリは以下のように配置されます。ここへパスを通せばいつものコマンドが実行できるわけです。

tree:test tree$ ll site-packages/bin/
total 24
-rwxr-xr-x  1 tree  staff   256B 12 17 22:54 fab
-rwxr-xr-x  1 tree  staff   256B 12 17 22:54 inv
-rwxr-xr-x  1 tree  staff   256B 12 17 22:54 invoke

先程run.shで実行したfabコマンドは↑これです。

雑感

AWS Lambdaでpythonランタイムを選択した際に、lamdaに標準インストールされていないモジュールを追加インストールする場合もローカルインストールする事になるので、この辺は覚えておくと色々と便利そうです。lambdaの件は以前以下の記事を書いたので、合わせてご覧下さい。

www.bunkei-programmer.net

また、冒頭で述べたようにセキュリティが非常に厳しい環境で、自分のアカウントのオーナー・グループ権限内に閉じて実行する事ができ、不要になった際にフォルダごと削除すれば消えてくれるのは安心感があります。

更に、グルーバルを汚染せずに済むので色々な人に易しくなりますね。