Python作為 Google Dropbox
的第三大開發語言、
的基礎語言已經已經越來越得到人們的喜愛,尤其是運維人員,而且很多優秀的運維工具都是Python開發的,引用Python作者的一句話:人生苦短,我用Python。
下面我就和大家簡單分享下我在用Python進行開發時使用的一些Python配置方面的小工具。
Python版本管理
我以前使用
pythonbrew
來管理我的開發機上面多個Python解析器,現在我使用
pyenv
來管理我的Python解析器,
github位址,安裝和使用直接見github裡面的README就行了,用起來還是比較簡單的,通過
pyenv
可以管理多個Python版本并共存,随時切換想要使用的版本,且這個工具本身不依賴于Python。
環境依賴
根據
12Factor規則,應用程式要顯示的聲明依賴,這裡我能想到的一個很好的例子是
Ruby
的
Gemfile
,這個檔案裡面聲明了一個
Ruby
應用程式所依賴的所有依賴,
Gemfile
就是對
Ruby
程式的
依賴聲明
,在Python裡面對依賴進行聲明我想到了
pip
。
依賴申明好了,不同的應用程式間如何進行依賴隔離呢,同樣
Ruby
程式是用
bundle exec
,這裡為什麼要提
Ruby
,那時因為我以前配置一個Ruby應用程式感覺非常友善,直接執行
script/bootstarp
所有依賴都安裝好了,基本直接運作程式就能跑了。
其實Python裡面也有一個非常好的依賴隔離的東西
virtualenv
,下面簡單介紹下基于
virtualenv
寫了一個簡單的Python項目類似
Ruby
bundle
的小工具。
Virtualenv Exec(ve)
源代碼如下:
#!/bin/bash
if [[ $# -le 0 ]]; then
echo "Usage: `basename $0` <command> [agrument]..."
fi
if [ -r "$HOME/.verc" ]; then
source "$HOME/.verc"
fi
if [ -z "$VIRTUALENV_DIR" ]; then
VIRTUALENV_DIR=".virtualenv"
fi
DIR=`pwd`
for (( ;; ))
do
if [ -r "$DIR/$VIRTUALENV_DIR/bin/activate" ]; then
source "$DIR/$VIRTUALENV_DIR/bin/activate"
if [ -n "$VIRTUAL_ENV" ]; then
break
fi
fi
if [ "$DIR" == "/" ]; then
break
fi
DIR=`dirname $DIR`
done
if [ -z "$VIRTUAL_ENV" ]; then
echo "virtualenv: not found"
echo
exit 1
else
if [ "$1" == "-v" ]; then
echo "virtualenv: $VIRTUAL_ENV"
echo
shift
fi
exec $@
fi
bootstrap.py
# -*- coding: utf-8 -*-
if __name__ == '__main__':
exit(1)
import os
import subprocess
import logging
import hashlib
import stat
logger = logging.getLogger(__name__)
class Bootstrap(object):
working_dir = None
bootstrap_dir = None
virtualenv_dir = None
def __init__(self, working_dir=None):
self.working_dir = working_dir or os.getcwd()
self.bootstrap_dir = self._config_dot_dir('BOOTSTRAP_DIR', '.bootstrap')
self.virtualenv_dir = self._config_dot_dir('VIRTUALENV_DIR', '.virtualenv')
if not os.path.isdir(self.bootstrap_dir):
os.makedirs(self.bootstrap_dir)
logger.debug('working_dir: %s', self.working_dir)
logger.debug('bootstrap_dir: %s', self.bootstrap_dir)
logger.debug('virtualenv_dir: %s', self.virtualenv_dir)
self.install_virtualenv()
self.install_ve()
def _config_dot_dir(self, env_name, default_value=None):
value = os.environ.get(env_name)
if not value:
return '%s/%s' % (self.working_dir, default_value)
logger.debug('config %s from envron', env_name)
if os.path.isabs(value):
return value
else:
return '%s/%s' % (self.working_dir, value)
def install_virtualenv(self):
if os.path.isfile('%s/%s' % (self.virtualenv_dir, 'bin/activate')):
return
executable = None
try:
executable = subprocess.check_output(['command', '-v', 'virtualenv-12.0.7/virtualenv.py'])
if not type(executable) is str:
# convert from bytes to str (unicode) under python3
executable = executable.decode()
executable = executable.strip()
except:
pass
if not executable:
virtualenv_tar = '%s/%s' % (self.bootstrap_dir, 'virtualenv.tar.gz')
executable = '%s/%s' % (self.bootstrap_dir, 'virtualenv-12.0.7/virtualenv.py')
self.download('http://mirrors.aliyun.com/pypi/packages/source/v/virtualenv/virtualenv-12.0.7.tar.gz',
virtualenv_tar, 'e08796f79d112f3bfa6653cc10840114')
os.system('tar -zxvf "%s" -C "%s"' % (virtualenv_tar, self.bootstrap_dir))
os.chdir(self.bootstrap_dir)
try:
os.system('%s --distribute --no-site-packages "%s"' % (executable, self.virtualenv_dir))
finally:
os.chdir(self.working_dir)
def download(self, source, target, hashing=None):
#if hashing and os.path.isfile(target) and hashing == self.md5sum(target):
#return
if os.system('wget "%s" -O "%s"' % (source, target)) == 0:
return
if os.system('curl "%s" -o "%s"' % (source, target)) == 0:
return
logger.error('Unable to download "%s"' % source)
raise RuntimeError
def mark_executable(self, path):
st = os.stat(path)
os.chmod(path, st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
def md5sum(self, filename):
return hashlib.md5(open(filename, 'rb').read()).hexdigest()
def install_ve(self):
executable = '%s/%s' % (self.bootstrap_dir, 've')
self.download('https://raw.github.com/baijian/ve/v1.1/ve',
executable, 'fd0f0601c6732ca9a5b3b62e691d68cb')
self.mark_executable(executable)
def ve(self, cmd):
os.system('%s/%s %s' % (self.bootstrap_dir, 've', cmd))
_bootstrap = None
__all_ = ['bootstrap', 've']
def bootstrap(working_dir=None):
global _bootstrap
_bootstrap = Bootstrap(working_dir)
def ve(cmd):
global _bootstrap
if not _bootstrap:
bootstrap()
_bootstrap.ve(cmd)
開始使用
- 建立項目目錄
mkdir project && mkdir project/script && cd project
- 編寫腳手架
#!/usr/bin/env python
# -*- coding: utf8 -*-
import os
source = "https://raw.github.com/baijian/bootstrap.py/v1.2/bootstrap.py"
target = "%s/bootstrap.py" % os.path.dirname(os.path.abspath(__file__))
if not os.path.isfile(target):
os.system("wget '%s' -O %s" % (source, target))
from bootstrap import bootstrap, ve
bootstrap(os.path.dirname(os.path.abspath(__file__)) + "/..")
ve("pip install requests==2.4.1")
- 修改依賴申明(可選)
編輯并修改script/bootstrap檔案
- 安裝項目依賴
script/bootstrap
- 檢視項目依賴
ve pip freeze
- 檢視項目使用的Python解析器
ve command -v python
其他
如果要使用Python進行web應用的開發,可以選用的架構諸如
Flask
、
Django
Tornado
web.py
,提到
web.py
,想到了網際網路之子
亞倫·斯沃茨
,有興趣可以看看他的視訊~
還有一些有些的優秀的Python運維工具諸如:
Ansible
Saltstack
Fabric
Supervisord
等,Python的開源子產品的品質非常高,這也是我喜歡Python的一個很重要的原因。