python - 在 Python 3.6 中使用 setuptools 打包后的 ModuleNotFoundError

标签 python python-3.x setuptools

我正在尝试使用 setuptools 从 Python3.6 应用程序生成一个包。虽然打包终止时没有错误,但 setuptools 生成的命令行程序无法导入包中的模块。 以下是我的项目的目录树。

.
├── MANIFEST.in
├── README.md
├── README.rst
├── contributors.txt
├── setup.cfg
├── setup.py
├── sonicparanoid
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── inpyranoid.cpython-36.pyc
│   │   ├── length_difference_filter.cpython-36.pyc
│   │   ├── ortholog_detection.cpython-36.pyc
│   │   ├── reads_stats.cpython-36.pyc
│   │   ├── seq_tools.cpython-36.pyc
│   │   ├── sonicparanoid.cpython-36.pyc
│   │   ├── sys_tools.cpython-36.pyc
│   │   └── workers.cpython-36.pyc
│   ├── bin
│   │   └── mmseqs
│   ├── blast_tools.py
│   ├── compile_inpyranoid_c.py
│   ├── compile_mmseqs_parser_c.py
│   ├── config.json
│   ├── example
│   │   ├── test_input
│   │   │   ├── chlamydia_trachomatis
│   │   │   ├── deinococcus_radiodurans
│   │   │   ├── gloeobacter_violaceus
│   │   │   └── thermotoga_maritima
│   │   └── test_output
│   │       └── README.txt
│   ├── inpyranoid.py
│   ├── inpyranoid_c.c
│   ├── inpyranoid_c.cpython-36m-darwin.so
│   ├── inpyranoid_c.pyx
│   ├── length_difference_filter.py
│   ├── mmseqs2_src
│   │   ├── README.txt
│   │   └── mmseqs.tar.gz
│   ├── mmseqs_parser_c.c
│   ├── mmseqs_parser_c.cpython-36m-darwin.so
│   ├── mmseqs_parser_c.pyx
│   ├── mmseqs_parser_cython.py
│   ├── ortholog_detection.py
│   ├── quick_multi_paranoid
│   │   ├── Makefile
│   │   ├── Makefile.in
│   │   ├── config
│   │   ├── dump.cpp
│   │   ├── gen_header.cpp
│   │   ├── hashtable.c
│   │   ├── hashtable.h
│   │   ├── hashtable.o
│   │   ├── hashtable_itr.c
│   │   ├── hashtable_itr.h
│   │   ├── hashtable_private.h
│   │   ├── ortholog.c
│   │   ├── qa.h
│   │   ├── qa1
│   │   ├── qa1.cpp
│   │   ├── qa2
│   │   ├── qa2.cpp
│   │   ├── qp
│   │   ├── qp.c
│   │   └── qps.c
│   ├── reads_stats.py
│   ├── seq_tools.py
│   ├── setup_sonicparanoid.py
│   ├── sonicparanoid.py
│   ├── sys_tools.py
│   ├── test_blast_tools.py
│   ├── test_length_difference_filter.py
│   ├── test_ortholog_detection.py
│   ├── test_reads_stats.py
│   ├── test_seq_tools.py
│   ├── test_sonicparanoid.py
│   ├── test_sys_tools.py
│   └── workers.py
└── user_manual.pdf

如果我运行 python3 sonicparanoid.py 它可以正常工作,但是如果我使用 setuptools 创建发行版,每当主程序 (sonicparanoid.py) 尝试导入任何包 (sonicparanoid) 目录中的其他 .py 模块。

以下是我的setup.py:

enter code here
from setuptools import setup, find_packages
from setuptools.extension import Extension
from Cython.Build import cythonize
import numpy

extensions = [
    Extension(
        "sonicparanoid.inpyranoid_c",
        ["sonicparanoid/inpyranoid_c.pyx"],
        include_dirs=[numpy.get_include()],
    ),
    Extension(
        "sonicparanoid.mmseqs_parser_c",
        ["sonicparanoid/mmseqs_parser_c.pyx"],
        include_dirs=[numpy.get_include()],
    ),
]


from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='sonicparanoid',
    version='0.0.2',  # Required
    description='Whatever',
    long_description=long_description,  # Optional
    url='http://iwasakilab.bs.s.u-tokyo.ac.jp/sonicparanoid/',  # Optional
    author='Me',
    author_email='my@email.com',
    classifiers=[  # Optional
        'Development Status :: 5 - Production/Stable',
        'Environment :: Console',
        'Intended Audience :: Science/Research',
        'Topic :: Scientific/Engineering :: Bio-Informatics',
        'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
    ],
    packages = ['sonicparanoid',], # Required
    install_requires=['numpy>=1.14.0', 'pandas>=0.22.0', 'cython>=0.27.0',     'sh>=1.12.14', 'setuptools>=24.2.0'], # specify minimum version
    python_requires='>=3.5, <3.7',
    ext_modules = cythonize(extensions, compiler_directives={'language_level': 3}),
    package_dir={'sonicparanoid': 'sonicparanoid/'},
    include_package_data=True,
    package_data={'sonicparanoid': ['example/test_output/*', 'example/test_input/*', 'mmseqs2_src/*', 'quick_multi_paranoid/*']
                },
    entry_points={  # Optional
        'console_scripts': [
            'sonicparanoid = sonicparanoid.sonicparanoid:main',
        ],
    },
)

sonicparanoid.py 中的 import 语句是这样的:

import os
import sys
import platform
import seq_tools as seqtools

目前,如果我执行 python3 sonicparanoid.py,一切正常,但是当我使用使用 setuptools 生成的程序时,出现以下错误:

Traceback (most recent call last):
  File "/usr/local/bin/sonicparanoid", line 11, in <module>
    load_entry_point('sonicparanoid==0.0.2', 'console_scripts',     'sonicparanoid')()
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 572, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2755, in load_entry_point
    return ep.load()
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2408, in load
    return self.resolve()
  File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py",     line 2414, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/usr/local/lib/python3.6/site-packages/sonicparanoid-0.0.2-py3.6-    macosx-10.13-x86_64.egg/sonicparanoid/sonicparanoid.py", line 5, in <module>
    import seq_tools as seqtools
ModuleNotFoundError: No module named 'seq_tools'

我已尝试使用此 question 中提出的解决方案, 但是如果我更改导入,例如 from sonicparanoid import seq_tools as seqtools 并运行 python3 sonicparanoid.py 我会收到导入错误 ImportError: cannot import name ' seq_tools 的

任何帮助将不胜感激,这是我第一次尝试打包,非常令人沮丧。

最佳答案

Python 使用 sys.path 查找模块/包并将脚本的目录添加到 sys.path 的开头。考虑到这一点,让我来看看导入的详细信息。

当您运行 python sonicparanoid/sonicparanoid.py 时,Python 会将目录 sonicparanoid/ 添加到 sys.path。现在,当目录位于 sys.path 中时,脚本可以直接导入 seq_tools,因为模块 seq_tools.py 位于 中的目录中系统路径.

当您安装包并运行生成的入口点 sonicparanoid 时,目录 sonicparanoid/ 不在 sys.path 中(但其父目录是) 并且 Python 无法导入 seq_tools。您必须将其导入为 sonicparanoid.seq_tools。但这意味着当您将 sonicparanoid.py 作为脚本运行时,您不能从 sonicparanoid.py 导入它!

底线:不要将 sonicparanoid.py 作为脚本运行,因为 sys.path 与运行入口点导入 sonicparanoid 差别太大包。

此外,您的脚本不得与 Python 包同名。当你有一个包 sonicparanoid 和一个脚本 sonicparanoid.py 并且脚本试图 import sonicparanoid — Python 尝试从脚本导入(因为它是 sys.path 中的第一个)而不是包并且失败了。

您可以将脚本命名为 sonicparanoid(没有 .py 扩展名 Python 不会尝试从中导入)或 sonic_paranoid.py 但不是sonicparanoid.py.

关于python - 在 Python 3.6 中使用 setuptools 打包后的 ModuleNotFoundError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48952408/

相关文章:

Python - 尝试添加评论时出错

python 隐式命名空间包未使用 setuptools 安装

python - 我如何告诉 'setup.py' 包含我的根目录中的文件以用于构建的发行版?

python - 为什么会出现▯这个字符?

python - 如何将 Tensorflow 数据集保存到文件中?

python - 使用一个文件搜索另一个文件,从找到的行创建新文件

python - comet (comet-ml) 无法与 Keras 一起运行

Python - 从具有多个类别的 csv 文件制作字典

python - 统计调查结果

python - setup.py install_requires 查找本地src包