分发带多个模块的Python命令行程序

1 投票
1 回答
722 浏览
提问于 2025-04-18 02:13

我正在尝试把一个用Python写的命令行程序发布给大家,但在此之前我想先测试一下,确保这个程序能正常工作。为此,我创建了一个简单的wheel格式的程序包,然后在另一个文件夹里创建了一个virtualenv环境,并把这个wheel安装到这个环境里。听起来很简单,对吧?

其实并没有那么简单。

当我在测试环境中尝试运行这个程序时,出现了这个错误信息:

Traceback (most recent call last):
  File "~/testing/bin/leprechaun", line 7, in <module>
    from leprechaun.main import main
  File "~/testing/lib/python3.4/site-packages/leprechaun/main.py", line 8, in <module>
    import generator
ImportError: No module named 'generator'

看起来是generator.py这个文件没有被导入,原因不明。不过奇怪的是,generator.pymain.py(程序的主要入口)是在同一个文件夹里的。

为了让大家更清楚,这里是我项目的目录结构:

├── leprechaun
│   ├── data
│   │   └── A bunch of text files that aren't important
│   ├── db.py
│   ├── generator.py
│   ├── __init__.py
│   ├── main.py
│   └── rainbow.py
├── LICENSE.txt
├── MANIFEST.in
├── README.rst
└── setup.py

另外,我的setup.py脚本是这样的:

#!/usr/bin/env python3

import re
from setuptools import setup, find_packages

version = re.search("^__version__\s*=\s*\"(.*)\"$",
  open("leprechaun/__init__.py").read(), re.M).group(1)

setup(
  name='leprechaun',
  version=version,
  description="A simple rainbow table generator",
  long_description=open("README.rst", encoding="utf-8").read(),
  author="My Name",
  author_email="My Email",
  url="https://github.com/zcdziura/leprechaun",
  license="MIT",
  packages=find_packages(),
  package_data={
    "leprechaun": ["data/wordlist*"]
  },
  entry_points={
    "console_scripts": [
      "leprechaun = leprechaun.main:main"
    ]
  }
)

我原以为生成的入口脚本会直接调用我包里的main函数,这样就能从同一个目录导入模块了。但看起来并不是这样。

那我该怎么解决这个问题呢?

1 个回答

1

你遇到的问题是关于绝对导入的。你可以看看这个PEP,了解一下背后的原因。

简单来说,现在你每次写的导入语句都会在sys.path中查找。而在Python 2.x中,你可以直接用import generator,它会在当前目录里找,但在Python 3.x中,它需要在指定的路径中查找。所以如果你改成from leprechaun import generator或者from . import generator,就能解决这个问题。

撰写回答