Create Python Devenv

古いメモを掘り起こしたので晒しておく。

Python開発環境の準備

開発環境の準備は面倒なのでAnsibleでplaybookを準備している。 Pythonについては自分用にAnsibleのplaybook内にpython3ってロールを書いてる。普段はこれを利用している。

とりあえず、Ansibleに書いてる事の方針とかをメモした。( pipenv よさそうだけど追いつけてないので今回は外してる)

(振り返るとなぜか拡張しづらい vars 配下でインストールパッケージを指定してるうえ ipython を書いてないので修正しておきたい。)

状況確認

Pythonは2系と3系に大きく別れている。特別な理由がない限り3系が推奨されている。 2018/01/14現在、2系はv2.7.14が3系はv3.6.4がlatestなので利用時には注意しておく。

処理系はCPython, PyPyなどがある。一般的な環境はCPythonで、PyPyはRPythonによるPython実装でJITコンパイルが提供されている。RPythonは型推定しやすいようにしたPythonのサブセットらしい。

以降では、Python書いた時は処理系にCPythonを暗に仮定している。他の環境でも成り立つかもしれないし成り立たないかもしれない。(単に検証と調査をしていない)

主流のパッケージマネージャはpipで easy_install を使って導入する。 easy_installpython と一緒にインストールされている。(場合によって easy_install3, pip3, pip3.6 の様にコマンドにバージョンが明記されている)

単一マシンであっても、複数の開発環境やシステムを分離して衝突しないようにしたいことが多い。 Pythonでは実行環境の仮想化に virtualenv 、またそのラッパーに virtualenvwrapper が準備されている。

今までの状況を整理すると下のような方針になる。

  • システムのpythonパッケージを最新にする
  • システムのPythonが2系ならばOSのパッケージマネージャで3系の最新バージョンを入れる
  • HOME/local/bin 配下にpython3(latest)をソースコードからビルドして入れる
  • local配下3系(latest)のeasy_installを使いpipをインストールする
  • pipを使い virtualenv, virtualenvwrapper をインストールする

準備の手順

CentOSは標準で2.7が含まれているのでうまいこと3系をインストールする。 OSXも標準で2.7が含まれているので brew install python3 などとしてインストールしておく。 システムに python3 が入ったら pip を準備する。

1
2
3
4
easy_install.sh pip
pip install pip --upgrade
sudo pip install virtualenv virtualenvwrapper
# .bashrc に設定が必要
1
2
sudo apt-get install python3-setuptools
sudo easy_install3 pip

virtualenv, virtualenvwrapper, pytest-pep8, pytest-flakes, mypy あたりは大抵必要になる。

1
2
3
4
sudo pip3 install virtualenv virtualenvwrapper
sudo pip3 install pytest-pep8 pytest-flakes mypy
# ipython
sudo pip3 install ipython==5.4.1

ロールに書いてない開発環境の設定

最近は Kotlin を書くのに IntelliJ IDEA 使っているので PyCharm でいいのではと思い始めているけどVim設定は大事。これはdotfiles に書いてる。タグジャンプするときの見た目と候補が過剰に多くなってて扱い難いけどvimの設定は下のように書いた。

ライブラリの場所を特定して $HOME/.cache/tags 配下にタグファイルを生成している。 各プロジェクトのタグファイルはカレントファイル以下に作成する。 .git ディレクトリなどを探索して使ってプロジェクトトップにタグファイルを置くようにする方がスマートだと思ってるけど面倒で修正できてない。

$HOME/dotfiles/scripts/vimenv.py に下のようなサポートスクリプトを書いている。 これによって開発環境の依存ライブラリの配置場所を特定している。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env python
# vim: fileencoding=utf-8

import sys, os

def main():
    for p in sys.path:
        if os.path.isdir(p):
            print(p)

if __name__ == "__main__":
    main()

利用するvimの設定はしたみたいにしている。選択肢が多い時のタグジャンプのUIを改善したい。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function! s:python_lib_path()
  return split(system('$HOME/dotfiles/scripts/vimenv.py'), '\n')
endfunction

let s:global_tags_path = $HOME."/.cache/tags"
" ライブラリ系 tags ファイルの集約箇所
if !isdirectory(s:global_tags_path)
  silent execute("!mkdir ".s:global_tags_path)
endif
function! s:get_tagdir(path) abort
  return s:global_tags_path."/". substitute(a:path, '/', '', 'g')
endfunction

" 必要なtagsファイルを立ち上げ時に追加する
for path in s:python_lib_path()
  let tagdir_path = s:get_tagdir(path)
  if !isdirectory(tagdir_path)
    silent execute("!mkdir ".tagdir_path)
  endif
  let tag_path = tagdir_path."/tags"
  if !filereadable(tag_path)
    silent execute("!ctags ".g:auto_ctags_tags_args." -f ".tag_path." ".path)
  endif
endfor

let s:base_tags = &tags
function! s:set_tags() abort
  execute('set tags='.s:base_tags)
  for path in s:python_lib_path()
    let tag_path = s:get_tagdir(path)."/tags"
    if filereadable(tag_path)
      execute('set tags+='.tag_path)
    endif
  endfor
endfunction
function! s:clean_tags() abort
  execute('set tags='.s:base_tags)
endfunction
call s:set_tags()
augroup python_tags
  autocmd!
  autocmd WinEnter,BufRead,FileType * if &filetype == 'python' | call s:set_tags() | else | call s:clean_tags() | endif
augroup END

nmap <buffer><nowait> <Leader>ds :split<CR>g<C-]>
nmap <buffer><nowait> <Leader>dv :vsplit<CR>g<C-]>
nmap <buffer><nowait> <Leader>i  K
comments powered by Disqus