python - 构建 python 模块,使其可以在带有和不带有 -m 开关的命令行中运行
问题描述
背景
我正在研究由许多脚本组成的 Python 模块。最终目标是在交互工作时使该模块中的函数可通过import
语句导入,并通过命令行参数使模块的某些部分可执行。
期望的结果
可以使用以下方式运行模块:
python -m ./my_module --help
# No -m switch
python ./my_module --help
结构
按照这个答案,我想了解-m
开关__main__.py
与__init__.py
文件的关系。目前的结构如下
__main__.py
# Shebang line
###########
# Modules #
###########
import argparse
import logging
import tempfile
###################
# Package modules #
###################
from utilities import check_directory_access
# ...
#################
# Run functions #
#################
def run(args):
"""Run all functions with provided arguments"""
# Start logging configuration
# If file is not provided use temporary file
if args.log_file is None:
args.log_file = tempfile.NamedTemporaryFile(delete=False,
prefix='my_module',
suffix='.log').name
# Create handlers: console
# logging configuration
logging.shutdown()
def main():
"""Process arguments and run main function"""
parser = argparse.ArgumentParser(description='Dop stuff module',
epilog='Epilog')
parser.add_argument("-t", "--tables", nargs='+', dest='tables',
help="List tables to refresh", type=str)
parser.add_argument("-l", "--log-file", dest='log_file',
type=str, help="Log file")
parser.set_defaults(func=run)
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
main()
__init__.py
###################
# Package modules #
###################
from .utilities import check_directory_access
# Other components
问题
跑步:
python -m my_module --help
退货
ImportError:没有名为“实用程序”的模块
然而
python my_module --help
工作没有问题
期望的结果
- 以声明
python my_module
和python -m my_module
工作的方式构建导入。 import my_module
交互工作时不会中断(奖励)不打电话就跑
python
解释器的情况下运行./my_module --help
。我不知道如何用树做到这一点:|-- my_module | |-- my_module.py | |-- __init__.py | |-- __main__.py | |-- module_component_A.py | |-- utilities.py
有没有具体的内容应该去
my_module.py
?
解决方案
Python 3 没有隐含的相对导入。使用绝对或显式相对导入:
from .utilities import check_directory_access
from my_module.utilities import check_directory_access
这使您的软件包可以与-m
交换机一起使用。它还允许import my_module
在交互式会话中。
存储为文件夹的裸包不能直接执行。这是由于操作系统本身造成的。如果您希望避免显式调用 python,则必须创建一个运行包的可执行文件。
将包存储为可执行 zip 文件,或创建运行包的脚本。
#!/usr/bin/env python3
import my_module.__main__
请注意,后者需要安装您的模块或直接与您的脚本相邻。如果您的模块可以安装,则console_scripts
entry_point
允许自动创建这样的脚本。
您不应该将脚本驻留在您的包中 - 这需要您更改sys.path
到父目录,这可能会导致重复的模块。例如,utilities.py
将作为单独的模块my_module.utilities
和 utilities
.
推荐阅读
- excel - 如何获取整个网页的内容
- typescript - 具有泛型的 Apollo 服务器快速返回类型
- python-3.x - x 秒后超时 discord.py 重写
- python - exe 文件可以修改包含的文本文件吗?
- node.js - 巢穴 | 配置模块 | 在 `validate` 函数中使用(或注入)服务
- python - Discord 机器人扩展运行良好,但不起作用
- python - jupyter notebook 中由 shift+tab 打开的帮助选项卡无法正确呈现方法/函数的文档字符串
- user-interface - 如何结合谷歌登录和普通登录?
- javascript - 如何在引导程序中创建自动完成搜索框?
- javascript - FAILURE:构建失败并出现异常。* 其中:构建文件 'C:\Users\mayev\dev\remplazo\Chronos\android\app\build.gradle' 行:81