从Fabric谈到dist-packages、site-packages和load_entry_point

来源:互联网 发布:匡靖 知乎 编辑:程序博客网 时间:2024/04/29 14:04

前段时间在一边学一边做一个Jave EE的项目。做到最后,需要部署的时候,组里的小兄弟用了一个叫Fabric的python工具结合Maven和Jetty来实现了打包成war文件并部署的功能。用法很简单,简介如下。

首先,写一个fabfile.py文件,放到某处,比如项目的根目录下,其内容完全是自定义以实现任何shell脚本可以做的事情。比如,下面这个:

from fabric.api import local, cd, env, run, sudoenv.hosts = ["server IP"]env.user = "user name"env.password = "password"env.git_password = "git_password"PROJECT_PATH = "some_path"def runserver():    local('mvn clean install -s settings_local.xml')    local('cd web && mvn jetty:run -s ../settings_local.xml')def deploy():    with cd(PROJECT_PATH):        # Pull latest code        run("git pull")        # Build war package        run("mvn package -s settings_local.xml")        # Restart Jetty        sudo("service jetty restart")


以上自定了2个函数runserver() 和 deploy(). 前一个函数是用于在本机开发的时候来起jetty的,而后一个函数适用于deploy到远端服务器上的。

使用方法很简单,如下:

fab runserverfab deploy

那么这个fab是什么呢?就是python写的工具Fabric,可以用于部署,也可以用于组合各种shell命令的。

安装Fabric的方法有2种,在ubuntu上。第一种方法是

sudo apt-get install fabric


第二种安装方法是

sudo pip install fabric


我都试了一下,惊奇地发现以下几个事实:

1. 如果是2台机器,A机器使用方法一安装,B机器使用方法二安装,那么结论如下:

1.1 在A机器上,'which fab'命令显示的fab存在地址是/usr/local/bin/fab,其内容如下:

#!/usr/bin/python# -*- coding: utf-8 -*-import reimport sysfrom fabric.main import mainif __name__ == '__main__':    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])    sys.exit(main())


1.2 在B机器上,'which fab'命令显示的fab存在地址是/usr/bin/fab, 其内容如下:

#! /usr/bin/python# EASY-INSTALL-ENTRY-SCRIPT: 'Fabric==1.8.2','console_scripts','fab'__requires__ = 'Fabric==1.8.2'import sysfrom pkg_resources import load_entry_pointif __name__ == '__main__':    sys.exit(        load_entry_point('Fabric==1.8.2', 'console_scripts', 'fab')()    )


1.3 在A机器上,实际的安装目录位于/usr/local/lib/python2.7/dist-packages/fabric 

     在B机器上,实际的安装目录位于/usr/lib/python2.7/dist-packages/fabric


2. 如果在同一台机器上,先用第一种方法(pip install)安装,再用第二种方法(apt-get install)安装,似乎第二种方法不起作用。


3. 我发现以前做的python项目的一些第三方package是放在site-packages下,而并非dist-packages下的。


以上的发现,不禁让人产生了下面的几个问题:

1、dist-packages和site-packages的区别是什么?


2、如何打包发布一个python的package?


3、1.2中的load_entry_point是何意思?


对于第一个问题,dist-packages和site-packages的区别是什么,stackover flow上有人给出了如下的解释:

dist-packages is a Debian-specific convention that is also present in its derivatives, like Ubuntu. Modules are installed to dist-packages when they come from the Debian package manager into this location:

/usr/lib/python2.7/dist-packages

Since easy_install and pip are installed from the package manager, they also use dist-packages, but they put packages here:

/usr/local/lib/python2.7/dist-packages

From the Debian Python Wiki:

dist-packages instead of site-packages. Third party Python software installed from Debian packages goes into dist-packages, not site-packages. This is to reduce conflict between the system Python, and any from-source Python build you might install manually.

This means that if you manually install Python from source, it uses the site-packages directory. This allows you to keep the two installations separate, especially since Debian and Ubuntu rely on the system version of Python for many system utilities.


这虽然解释了dist-packages的一些事情,但我还没明白最后一段所说的如何手动从源码安装以至于会生成在site-packages里。这是一个TODO的问题。


对于第2个问题,在前一篇博客《把自己的Python脚本打包上传到PyPI》里已经做了基本的描述。


对于第3个问题,这篇文章 http://www.cnblogs.com/babykick/archive/2012/03/09/2387808.html 做了一些描述。要点就是,在setup.py中加入对entry_points的定义,这样将来在xxx.egg-info目录下的entry-points.txt文件里就会有相应的程序入口点的信息。

为了写出具有load_entry_point()效果的package,我改写了前一篇博客《把自己的Python脚本打包上传到PyPI》里面的setup.py。并且,我意识到前一篇博客中上传的package的名字似乎不符合行业规范,因为没有用全小写字母。所以,改写后的setup.py如下,并且改了package的名字为funds_data了。

from setuptools import setup, find_packagesPACKAGE = "funds_data"NAME = "funds_data"DESCRIPTION = "This package can download funds data from http://huobijijin.com and then analyze the data for giving valuable funds."AUTHOR = "Finix Lei"AUTHOR_EMAIL = "finixlei@gmail.com"URL = "https://github.com/FinixLei/FundsData"VERSION = __import__(PACKAGE).__version__setup(    name=NAME,    version=VERSION,    description=DESCRIPTION,    # long_description=read("README.md"),    author=AUTHOR,    author_email=AUTHOR_EMAIL,    license="Apache License, Version 2.0",    url=URL,    packages=find_packages(),    classifiers=[        "Development Status :: 3 - Alpha",        "Environment :: Web Environment",        "Intended Audience :: Developers",        "Operating System :: OS Independent",        "Programming Language :: Python",    ],    entry_points={        'console_scripts': [            'funds_data = funds_data.funds_data:main',            ]    },    zip_safe=False,)

运行效果就是:

首先,利用pip去安装这个package:

sudo pip install funds_data


然后就可以直接运行

funds_data
直接看到结果了。

深究一下funds_data的内容,那么就是:

finix@ubuntu:/usr/local/lib/python2.7/dist-packages$ which funds_data/usr/local/bin/funds_datafinix@ubuntu:/usr/local/lib/python2.7/dist-packages$ cat /usr/local/bin/funds_data#!/usr/bin/python# EASY-INSTALL-ENTRY-SCRIPT: 'funds-data==0.98','console_scripts','funds_data'__requires__ = 'funds-data==0.98'import sysfrom pkg_resources import load_entry_pointif __name__ == '__main__':    sys.exit(        load_entry_point('funds-data==0.98', 'console_scripts', 'funds_data')()    )finix@ubuntu:/usr/local/lib/python2.7/dist-packages$ 


这样,终于写出了安装后具有entry_point效果的自制package了!

1 0
原创粉丝点击