使用带有多个main()函数的console_scripts

时间:2016-07-04 06:03:53

标签: python setup.py

如何使用多个函数构建一个console_scripts条目(不包含在单个main函数中),并且您不是该脚本的作者?

背景阅读Python: migrate setup.py "scripts=" to entry_points。当要调用的脚本在没有参数的单个启动函数中具有所有期望的操作时,前一个问题中的答案是成功的,例如:

if '__name__' == '__main__':
    main_do_all()

并且setup.py条目是:

entry_points = {
    'console_scripts': ['foobar = foobartools.foobar_cli:main_do_all'],
} 

然而,它并不适合在顶层使用多个功能来执行其操作的脚本:

if '__name__' == '__main__':
    prologue(sys.argv)
    do_thing()
    finish()

...因为console_scripts只能命名一个函数并且不能使用参数(对吗?)

我一直在想我们需要的是编写一个只包含一个函数的包装器脚本 - 运行真实脚本 - 然后在setup.py中调用它。然而,阅读exec(),execfile(),subprocess(),popen()它看起来像一堆蠕虫,我早期尝试使用exec()表现不佳,让我怀疑这种方法。

对于一个试验台,引发这个问题的时刻程序是mutagen,尽管我已经遇到过其他情况。

这样做的正确方法是什么?

测试用例和结果

(如果是复制和粘贴错误,另请参阅https://gist.github.com/maphew/865c02c9143fd954e5653a8ffb1fb441

./ my_cli / single_main.py:

# This works when 1st 3 functions are in the same file, but what to do when
# they're somewhere else, and meant to be called as a commandline script?

import sys

# --- copied from 'tools/multi_main' but we really want to run in-situ ---
def prologue(argv):
    print("Arguments recieved: {}".format(argv))

def do_thing():
    print("Doing something here")

def finish():
    print("All done now, cleaning up")
# --- end external ---

def main():
    prologue(sys.argv)
    do_thing()
    finish()

if __name__ == '__main__':
    print("Running 'single_main' script")
    main()

./ my_cli / cli.py:

# ./my_cli/cli.py
# wrapper created for console_scripts to run 'tools/multi_main'

import os
import sys

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

def multi_main(argv):
    fname = os.path.join(here, '../tools', 'multi_main.py')
    print(fname)
    with open(fname) as f:
        code = compile(f.read(), fname, 'exec')
        #exec(code, global_vars, local_vars)
        exec(code)

if __name__ == '__main__':
    multi_main(sys.argv)

./工具/ multi_main:

# ./tools/multi_main
# This file from upstream source. We want to avoid editing.

import sys

def prologue(argv):
    print("Arguments recieved: {}".format(argv))

def do_thing():
    print("Doing something here")

def finish():
    print("All done now, cleaning up")

if __name__ == '__main__':
    print("Running 'multi_main' script")
    prologue(sys.argv)
    do_thing()
    finish()

./ setup.py:

#./setup.py

import os
from setuptools import setup

setup(
    name="multi_main",
    description="Migrating from scripts to console_scripts entry points",
    # Old, 'nix-only way
    scripts=[os.path.join("tools", name) for name in [
        "multi_main",
        ]],
    # new, multi-platform way (when get to working)
    entry_points = {
        'console_scripts': [
            'my_single_main = my_cli.single_main:main',
            'my_multi_main = my_cli.cli:multi_main',
            ],
        },
    )

Shell日志:

[py34_x64] D:\b\code\console_script_multi
> pip install -e .
Obtaining file:///D:/b/code/console_script_multi
Installing collected packages: multi-main
  Running setup.py develop for multi-main
Successfully installed multi-main-0.0.0

[py34_x64] D:\b\code\console_script_multi
> my_single_main
Arguments recieved: ['C:\\Python34_x64\\Scripts\\my_single_main-script.py']
Doing something here
All done now, cleaning up

[py34_x64] D:\b\code\console_script_multi
> my_multi_main
Traceback (most recent call last):
  File "C:\Python34_x64\Scripts\my_multi_main-script.py", line 9, in <module>
    load_entry_point('multi-main==0.0.0', 'console_scripts', 'my_multi_main')()
TypeError: multi_main() missing 1 required positional argument: 'argv'

[py34_x64] D:\b\code\console_script_multi
> multi_main
'multi_main' is not recognized as an internal or external command,
operable program or batch file.

[py34_x64] D:\b\code\console_script_multi
> python c:\Python34_x64\Scripts\multi_main
Running 'multi_main' script
Arguments recieved: ['c:\\Python34_x64\\Scripts\\multi_main']
Doing something here
All done now, cleaning up

[py34_x64] D:\b\code\console_script_multi
>

0 个答案:

没有答案