如何 pip 安装 Python 程序,使其具有命令行快捷方式

How to pip install a Python program such that it has a command line shortcut

我正在尝试编写一个 Python 程序,我可以 pip install 使其具有特定的命令行别名,类似于带有 [= 的 'aws' 命令17=] 包 (cf. https://pypi.python.org/pypi/awscli/1.11.115).

awscli 中的 setup.py 似乎包含类似

的内容
setuptools.setup(console='bin/aws')

这大概是使命令行 'alias' 起作用的原因。但是,在 http://setuptools.readthedocs.io/en/latest/setuptools.html 我无法轻松找到有关如何使用此 console 选项的文档或示例。

我的简化用例如下。我有一个目录 sayhello,其中包含以下内容:

.
├── sayhello.py
└── setup.py

其中 sayhello.py 定义了函数 (say_hello) 和调用此函数的 if __name__ == "__main__" 块:

def say_hello():
    print("Hello, world!")

if __name__ == "__main__":
    say_hello()

我试过的setup.py

from setuptools import setup, find_packages

setup(name="sayhello", version="1.0", packages=find_packages(), console="/bin/sayhello")

然后在sayhello目录下,我做

pip install .

(在 virtualenv venvsource venv/bin/activate 之后在虚拟环境中完成)。在此之后,例如,我可以在 Python shell 中 import sayhellosayhello.say_hello(),但是我尝试定义的键盘快捷键 sayhello 没有没用。

如何修改 setup.py 以便命令 sayhello 触发 sayhello.py 中的 if __name__ == "__main__" 块?

假设您的包的根目录中有一个 sayhello.py。然后只需在 setup.py:

中添加 scripts
setup(
    ...
    scripts=['sayhello.py']
)

通常将所有脚本放在 scripts/ 目录中,使它们可执行,并在第一行放置一个 hashbang (#!/usr/bin/env python)。

第二种方法是通过console_scripts:

setup(
    ...
    entry_points = {
        'console_scripts': ['sayhello=sayhello:say_hello'],
    }
    ...
)

一个最小的例子

sayhello.py中输入:

#!/usr/bin/env python
print "Hello!"

setup.py中:

from setuptools import setup
setup(
    name="sayhello",
    version="0.0.1",
    scripts=['sayhello.py']
)

在 运行 pip install . 之后,您应该将 sayhello.py 脚本复制到虚拟环境的 bin 目录(在您的 PATH 中)。

测试脚本:

$ sayhello.py
Hello!

首先,我认为您需要将 sayhello.py 放入带有 __init__.py 的目录中,以便 find_packages 找到它(这是 entry_points 方法)。我不确定(我从来没有尝试过),但我现在一直在尝试,没有它就无法工作。

我知道有两种创建命令行可运行脚本的方法:entry_points and scripts.

entry_points 是更强大的选项,但需要脚本的功能成为包的一部分(意味着它位于包的模块中。如果将 sayhello.py 移动到 sayhello 目录和 __init__.py 文件,它看起来像这样:

entry_points={
    'console_scripts': [
        'say_hello = sayhello.sayhello:say_hello'
    ]
}

更简单的选项是scripts。只需添加:

scripts=['sayhello.py']

这是我正在使用的东西:

setup.py

从 setuptools 导入设置,find_packages

setup(
    name="sayhello",
    version="1.0",
    packages=find_packages(),
    entry_points = {
        'console_scripts': [
            "sayhello = sayhello.sayhello:say_hello"
        ]
    }
)

目录结构:

.
├── sayhello
│   ├── __init__.py
│   └── sayhello.py
└── setup.py

sayhello.py

def say_hello():
    print("Hello, world!")

if __name__ == "__main__":
    say_hello()