我的 Python 开发工作流程
这是开发 Python 包的基本过程,其中包含我认为是社区中的最佳实践。这是基本的——如果你真的很想开发 Python 包,还有更多内容,每个人都有自己的偏好,但它应该作为开始的模板,然后了解更多关于所涉及的部分。基本步骤是:
虚拟环境
首先,我建议使用virtualenv
一个隔离的环境来开发你的包。在开发过程中,你需要安装、升级、降级和卸载包的依赖项,你不希望
- 您的开发依赖项会污染您的系统范围
site-packages
- 在整个系统范围
site-packages
内影响您的开发环境
- 版本冲突
污染您的系统范围site-packages
是不好的,因为您安装的任何包都将可用于您安装的所有使用系统 Python 的 Python 应用程序,即使您的小项目只需要该依赖项。它刚刚安装在一个新版本中,覆盖了系统范围内的版本site-packages
,并且与依赖它的 ${important_app} 不兼容。你明白了。
让您的系统广泛site-packages
影响您的开发环境是不好的,因为您的项目可能依赖于您已经在系统 Python 的site-packages
. 因此,您忘记正确声明您的项目依赖于该模块,但一切正常,因为它始终存在于您的本地开发盒中。直到你发布你的包并且人们尝试安装它,或者将它推送到生产环境等等......在一个干净的环境中开发会迫使你正确地声明你的依赖关系。
因此,virtualenv是一个独立的环境,具有自己的 Python 解释器和模块搜索路径。它基于您之前安装的 Python 安装,但与它隔离。
要创建 virtualenv,请通过使用或virtualenv
将其安装到系统范围的 Python 来安装包:easy_install
pip
sudo pip install virtualenv
请注意,这将是您以 root 身份(使用 sudo)将某些东西安装到您的全局站点包中的唯一一次。之后的一切都将发生在您即将创建的 virtualenv 中。
现在创建一个 virtualenv 来开发你的包:
cd ~/pyprojects
virtualenv --no-site-packages foobar-env
这将创建一个目录树~/pyprojects/foobar-env
,即您的 virtualenv。
要激活 virtualenv,cd
进入它source
和bin/activate script
:
~/pyprojects $ cd foobar-env/
~/pyprojects/foobar-env $ . bin/activate
(foobar-env) ~/pyprojects/foobar-env $
注意前面的点.
,它是source
shell 命令的简写。还要注意提示的变化:(foobar-env)
意味着你在激活的 virtualenv 中(并且总是需要隔离才能工作)。因此,每次打开新的终端选项卡或 SSH 会话等时都要激活您的环境。
如果您现在python
在该激活的环境中运行,它实际上将~/pyprojects/foobar-env/bin/python
用作解释器,具有自己的site-packages
和隔离的模块搜索路径。
安装工具包
现在用于创建您的包。基本上,您需要一个setuptools
带有 a 的包setup.py
来正确声明包的元数据和依赖项。您可以按照setuptools 文档自行执行此操作,或使用Paster 模板创建包骨架。要使用 Paster 模板,请安装PasteScript
到您的 virtualenv 中:
pip install PasteScript
让我们为我们的新包创建一个源目录以使事情井井有条(也许您希望将项目拆分为多个包,或者稍后使用源中的依赖项):
mkdir src
cd src/
现在创建你的包,做
paster create -t basic_package foobar
并回答交互式界面中的所有问题。大多数是可选的,只需按 ENTER 即可保留默认值。
这将创建一个名为foobar
. 这是这个名字
- 人们将使用
easy_install
或pip install foobar
- 其他包将用于依赖于您的名称
setup.py
- 在PyPi上会叫什么
在内部,您几乎总是创建一个名为相同的 Python 包(如在“带有 的目录中__init__.py
)。这不是必需的,顶级 Python 包的名称可以是任何有效的包名称,但命名它是一种通用约定与发行版相同。这就是为什么将两者分开很重要但并不总是那么容易的原因。因为顶级python包名称是什么
- 人们(或您)将使用
import foobar
或from foobar import baz
因此,如果您使用了 paste 模板,它已经为您创建了该目录:
cd foobar/foobar/
现在创建您的代码:
vim models.py
models.py
class Page(object):
"""A dumb object wrapping a webpage.
"""
def __init__(self, content, url):
self.content = content
self.original_url = url
def __repr__(self):
return "<Page retrieved from '%s' (%s bytes)>" % (self.original_url, len(self.content))
并且client.py
在同一目录中使用models.py
:
client.py
import requests
from foobar.models import Page
url = 'http://www.stackoverflow.com'
response = requests.get(url)
page = Page(response.content, url)
print page
requests
声明对模块的依赖setup.py
:
install_requires=[
# -*- Extra requirements: -*-
'setuptools',
'requests',
],
版本控制
src/foobar/
是您现在要置于版本控制之下的目录:
cd src/foobar/
git init
vim .gitignore
.gitignore
*.egg-info
*.py[co]
git add .
git commit -m 'Create initial package structure.
将您的软件包安装为开发鸡蛋
现在是时候在开发模式下安装你的包了:
python setup.py develop
这将安装requests
依赖项和您的包作为开发鸡蛋。所以它被链接到你的 virtualenv 的站点包中,但仍然存在于src/foobar
你可以进行更改的地方,并让它们在 virtualenv 中立即处于活动状态,而无需重新安装你的包。
现在对于您最初的问题,使用相对路径导入:我的建议是,不要这样做。现在您已经有了一个正确的 setuptools 包,它已安装并可导入,您当前的工作目录应该不再重要了。只需执行from foobar.models import Page
或类似操作,声明该对象所在的完全限定名称。对于您自己和其他阅读您的代码的人来说,这使您的源代码更具可读性和可发现性。
您现在可以通过python client.py
在您激活的 virtualenv 中的任何地方运行您的代码。python src/foobar/foobar/client.py
工作正常,您的软件包已正确安装,您的工作目录不再重要。
如果您想更进一步,您甚至可以为您的 CLI 脚本创建一个 setuptools 入口点。这将在您的 virtualenv 中创建一个bin/something
脚本,您可以从 shell 运行该脚本。
setuptools 控制台脚本入口点
setup.py
entry_points='''
# -*- Entry points: -*-
[console_scripts]
run-fooobar = foobar.main:run_foobar
''',
client.py
def run_client():
# ...
main.py
from foobar.client import run_client
def run_foobar():
run_client()
重新安装您的软件包以激活入口点:
python setup.py develop
你去吧,bin/run-foo
。
一旦你(或其他人)在 virtualenv 之外真正安装了你的包,入口点将在/usr/local/bin/run-foo
或类似的地方,它会自动在$PATH
.
进一步的步骤
推荐阅读: