3

我面临与此处提出的问题类似的情况:Python Import error on installed ruamel.yaml in custom directory

我知道我们将希望使用某种形式的 python 环境隔离机制,如 virtualenv 来创建可以运行我们的 python 代码的隔离环境。然而,在我所在的行业中,我们编写几个 python 包的情况并不少见,这些包将需要在其他带有自己的 python 解释器的现成软件中使用,因此我们受到限制软件(例如autodesk maya)使用的python版本,我们没有使用virtualenv的灵活性。

pip install --install-option="--prefix=\\vm-fs-001\prod\sww\proj\general\python\python-2.7.14" <package_name>

我们使用与上述命令类似的东西将我们写入的这些代码部署到自定义的 3rd 方目录中。我们将环境设置为包含第 3 方部署文件夹的站点包和脚本。

PYTHONPATH=\\vm-fs-001\prod\sww\proj\general\python\python-2.7.14\Lib\site-packages;%PYTHONPATH%

PATH=\\vm-fs-001\prod\sww\proj\general\python\python-2.7.14\Scripts;%PATH%;

在这种情况下,该软件与 python 2.7.14 解释器捆绑在一起,我们编写了一个需要 ruamel.yaml 的包

尝试在 3rd 方软件的 python 解释器中导入 ruamel.yaml 时出现以下错误。

ImportError: No module named ruamel.yaml

即使我要从标准 python 2.7.14 解释器中导入 ruamel,我也会得到相同的 ImportError。

λ python
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ruamel.yaml
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named ruamel.yaml
>>> import sys
>>> sys.path
['', '\\\\vm-fs-001\\prod\\sww\\proj\\general\\python\\python-2.7.14\\Lib\\site-packages', 'C:\\windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27', '\\\\vm-dc-001\\RedirectedFolders$\\nelson.lim\\AppData\\Roaming\\Python\\Python27\\site-packages', 'C:\\Python27\\lib\\site-packages']
>>>

但是,如果我在__init__.py此处添加:\\vm-fs-001\prod\sww\proj\general\python\python-2.7.14\Lib\site-packages\ruamel\__init__.py并使 ruamel 文件夹成为包而不是命名空间文件夹,则导入错误将消失。

导入带有安装在自定义文件夹中的命名空间的包似乎存在问题。

我该如何解决这个问题?

4

1 回答 1

0

命名空间是个好主意,但不幸的是,命名空间包的实现存在一些问题,ruamel.yaml安装程序必须解决这些问题。尽管我没有对安装程序中的文件执行任何操作.pth,但-ed 安装似乎并没有以与非前缀安装相同的方式处理这些文件。ruamel.yaml--prefix

ruamel.yaml安装程序是数据驱动的,并且在setup.py许多软件包之间是通用的。在没有任何功能改进的情况下,重写和测试所有这些将花费大量时间,并且到目前为止没有人愿意为此付费(而且可能最好花在改进命名空间包机制上)。

除了完全重新打包之外ruamel.yaml,您应该能够在 ruamel/__init__.py加载自己的包之前创建 if 它不存在from ruamel.yaml import YAML(假设您的包依赖于ruamel.yaml)。如果ruamel.yaml是可选安装,或者作为一般解决方法,我建议您创建一个包ruamel_yaml来创建该文件(即PREFIX/ruamel/__init__.py),__init__.py如果该文件不存在,则在其中创建from ruamel.yaml import *.

当您使用以下方法进行前缀安装时,这种方法至少适用于基于 Linux 的安装:

pip install --prefix=/path/to/some/directory ruamel_yaml-0.1-py2.py3-none-any.whl

Asetup.py创建这样一个包:

from setuptools import setup

import os
from textwrap import dedent

pkg = 'ruamel_yaml'
os.makedirs(pkg)
with open(pkg + '/__init__.py', 'w') as fp:
    fp.write(dedent("""\
    import sys
    import os

    fn = __file__.replace('ruamel_yaml', 'ruamel').replace('__init__.pyc', '__init__.py')
    if not os.path.exists(fn):
        with open(fn, 'w'):
            pass

    from ruamel.yaml import *
    """))

with open('setup.cfg', 'w') as fp:
    fp.write('[bdist_wheel]\nuniversal = 1\n')


setup(name=pkg,
      version='0.1',
      description='wrapper for --prefix installations of ruamel.yaml',
      author='Your Name',
      url='http://someurl.com',
      author_email='your@email',
      license='MIT',
      install_requires=['ruamel.yaml'],
      packages=[pkg],
      zip_safe=False)

创建ruamel_yaml-0.1-py2.py3-none-any.whl

pip install wheel
python setup.py bdist_wheel

如有必要,生成__init__.py的文件还应执行“使 ruamel 文件夹成为包而不是命名空间文件夹”的步骤(我不清楚这意味着什么),如果 Windows/Maya 需要这样做的话。

于 2018-04-05T19:21:56.603 回答