天天看點

Python環境配置

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的一個很重要的原因。