【问题标题】:Where in a virtualenv does the custom code go?自定义代码在 virtualenv 中的哪个位置?
【发布时间】:2010-12-19 11:34:12
【问题描述】:

使用virtualenv 时应该遵循什么样的目录结构?例如,如果我正在构建一个 WSGI 应用程序并创建了一个名为 foobar 的 virtualenv,我将从以下目录结构开始:

/foobar
  /bin
    {activate, activate.py, easy_install, python}
  /include
    {python2.6/...}
  /lib
    {python2.6/...}

一旦创建了这个环境,人们会将自己的位置放在哪里:

  • python 文件?
  • 静态文件(图像/等)?
  • “定制”包,例如那些在线提供但在奶酪店找不到的包?

virtualenv 目录有关?

(假设我已经知道where the virtualenv directories themselves should go。)

【问题讨论】:

  • @jkp:我不同意。如何布局 Python 应用程序与如何在 virtualenv 中为开发目的定位该应用程序是不同的。它是相关的,但不一样。请不要关闭为重复。

标签: python project virtualenv


【解决方案1】:

virtualenv 提供 python 解释器实例,而不是应用程序实例。您通常不会在包含系统默认 Python 的目录中创建应用程序文件,同样也不需要在 virtualenv 目录中找到您的应用程序。

例如,您可能有一个项目,其中有多个应用程序使用相同的 virtualenv。或者,您可能正在使用 virtualenv 测试应用程序,该应用程序稍后将使用系统 Python 进行部署。或者,您可能正在打包一个独立的应用程序,将 virtualenv 目录放在应用程序目录本身的某个位置可能是有意义的。

所以,总的来说,我认为这个问题没有一个正确的答案。而且,virtualenv 的一个好处是它支持许多不同的用例:不需要一种正确的方式。

【讨论】:

  • 同意。我所做的一切都使用 virtualenv,而且我从不将文件放在 virtualenv 目录中。 Virtualenv 不需要对您的项目结构产生影响;只需激活 virtualenv(或使用它的 bin/python),然后在您拥有它们的任何地方处理您的文件。
  • 我也完全同意。我曾经接触过我的 virtualenv 中的任何文件(我使用 virtualenvwrapper)的唯一一次是当我想编辑 postactivatepostdeactivate 挂钩时。
  • 将您的项目与virtualenv 目录分开会更干净,但是将virtualenv 与系统python 进行比较是没有帮助的,因为virtualenv 的目的是修复损坏的依赖项并隔离项目,所以他们可以使用不同的包版本,甚至是 python 版本(我意识到这是在 python3 之前编写的)。允许应用程序共享 virtualenv 就像使用系统 python 一样使用 virtualenv,使应用程序容易受到 virtualenv 旨在解决的相同问题的影响。 There should be one obvious way to do it;逻辑上应该是 1:1
  • @Ned:试图获得一些最佳实践,但仍不清楚:如果您有几十个项目,每个项目都有自己的 virtualenv,那么您如何跟踪哪个项目与哪个 virtualenv 一起使用?在每个文件夹的根目录中添加小 shell 脚本,并使用您使用的 virtualenv 的名称?
【解决方案2】:

如果您经常只有几个项目,没有什么能阻止您为每个项目创建一个新的 virtualenv,并将您的包直接放入其中:

/foobar
  /bin
    {activate, activate.py, easy_install, python}
  /include
    {python2.6/...}
  /lib
    {python2.6/...}
  /mypackage1
    __init__.py
  /mypackage2
    __init__.py

这种方式的好处是总能确保找到里面属于项目的activate脚本。

$ cd /foobar
$ source bin/activate
$ python 
>>> import mypackage1
>>>

如果您决定更有条理,您应该考虑将所有 virtualenvs 放在一个文件夹中,并以您正在处理的项目命名。

  /virtualenvs
    /foobar
      /bin
        {activate, activate.py, easy_install, python}
      /include
        {python2.6/...}
      /lib
        {python2.6/...}
  /foobar
    /mypackage1
      __init__.py
    /mypackage2
      __init__.py

这样,当出现问题时,您始终可以使用新的 virtualenv 重新开始,并且您的项目文件保持安全。

另一个优点是您的多个项目可以使用相同的 virtualenv,因此如果您有很多依赖项,您不必一遍又一遍地进行相同的安装。

$ cd /foobar
$ source ../virtualenvs/foobar/bin/activate
$ python 
>>> import mypackage2
>>>

对于经常需要设置和拆除 virtualenvs 的用户来说,看看 virtualenvwrapper 是有意义的。

http://pypi.python.org/pypi/virtualenvwrapper

使用 virtualenvwrapper 你可以

* create and delete virtual environments

* organize virtual environments in a central place

* easily switch between environments

在处理“foo”和“bar”项目时,您不必再担心您的虚拟环境在哪里:

  /foo
    /mypackage1
      __init__.py
  /bar
    /mypackage2
      __init__.py

这就是你开始处理项目“foo”的方式:

$ cd foo
$ workon
bar
foo
$ workon foo
(foo)$ python
>>> import mypackage1
>>>

然后切换到项目“bar”就这么简单:

$ cd ../bar
$ workon bar
(bar)$ python
>>> import mypackage2
>>>

很整洁,不是吗?

【讨论】:

  • 强烈同意这个关于使用virtualenvwrapper的回答。它巧妙地将 virtualenv 抽象出来,同时仍然为您提供所有好处。
  • 但强烈不同意将您的代码放在虚拟环境中。如果您希望它“靠近”文件系统上的项目,则将 venv/ 目录与项目的 BASE_DIR 放在同一级别。
【解决方案3】:

因为 virtualenvs 不可重定位,我认为将项目文件放在 virtualenv 目录中是不好的做法。 virtualenv 本身是一个生成的开发/部署工件(有点像 .pyc 文件),不是项目的一部分;它应该很容易吹走并随时重新创建,或者在新的部署主机上创建一个新的,等等。

事实上,很多人使用virtualenvwrapper,它几乎完全从你的意识中移除了实际的virtualenvs,默认情况下它们都并排放置在$HOME/.virtualenvs 中。

【讨论】:

  • 完全同意这是一种不好的做法,很高兴指出它应该很容易被吹走和重新创建,特别是对于测试部署和削减不需要的需求包。只想添加 virtualenv 可以使用例如重新定位virtualenv --relocatable myvenvstackoverflow.com/a/6628642/1335793 仅仅因为你可以并不意味着你应该这样做。
【解决方案4】:

如果你给你的项目一个setup.py,pip 可以直接从版本控制中导入它。

做这样的事情:

$ virtualenv --no-site-packages myproject
$ . myproject/bin/activate
$ easy_install pip
$ pip install -e hg+http://bitbucket.org/owner/myproject#egg=proj

-e 会将项目放入myproject/src,但会将其链接到myproject/lib/pythonX.X/site-packages/,因此您所做的任何更改都将立即在从本地site-packages 导入的模块中获取。 #egg 位告诉 pip 你想给它为你创建的 egg 包起什么名字。

如果您不使用--no-site-packages,请注意使用-E 选项指定您希望将pip 安装到virtualenv 中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多