我几个月来一直在努力为我的项目创造一个轮子而挣扎着#rpn' (https://github.com/ConceptJunkie/rpn)。我终于找到了一切正常的地步,除了我试图在setup.py中创建的控制台命令。
我的项目有多个模块,我将在下面发布的setup.py创建一个似乎正常工作的轮子。我还没有使用virtualenv进行过广泛的测试,因为我希望得到正确的基础知识。当我用pip安装滚轮时,我可以运行python并导入我的模块并运行这些功能就好了。但是,我使用项目(和一些辅助工具)作为命令行应用程序,所以我希望轮子为我创建一些命令。
我在Windows上,所以当我安装滚轮时,它会为我定义的每个命令创建一个小的EXE文件,但是当我尝试运行命令时,我得到了这个输出:
c:\app\python36\scripts>makeRPNUnits.exe
Traceback (most recent call last):
File "c:\app\python36\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\app\python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\app\python36\Scripts\makeUnits.exe\__main__.py", line 5, in <module>
ImportError: cannot import name '__main__'
这是我需要运行以准备应用程序使用的数据文件的一个小实用程序,但其他命令都执行相同的操作。如果我使用Python,我可以运行它:
c:\app\python36\scripts>python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import makeUnits
>>> makeUnits.main( )
makeUnits 6.999.13 (7.0b13) - RPN command-line calculator unit conversion data generator
copyright (c) 2018 (1988), Rick Gutleber (rickg@his.com)
[and so on...]
我也可以通过Python使用实际的应用程序:
>>> rpn.handleOutput( rpn.rpn( [ '2', '2', '+' ] ) )
4
我花了好几个小时寻找帮助......设置工具的文档非常稀疏且不透明,我只能在其他地方找到很小的信息片段而且它经常相互冲突。从来没有足够理解细节,但足以做出有根据的猜测。
我的目录结构如下所示:
rpn/
├── rpndata
│ ├── various_text_files
└── setup.py
__init__.py
rpn.py
makeUnits.py
makeHelp.py
MANIFEST.in
rpn*.py
我想要创建的每个命令都在一个处理 main 的单独模块中表示。例如:
if __name__ == '__main__':
main( )
,其余文件实现程序和各种实用程序使用的所有功能。同样,大部分内容都在Python中运行,但/ python36 / scripts中的命令失败并出现上述错误。
整个setup.py相当冗长,但相关部分是:
entry_points = {
'console_scripts': [
'rpn = rpn.rpn:__main__',
'makeRPNHelp = rpn.makeHelp:__main__',
'makeRPNUnits = rpn.makeUnits:__main__',
'prepareRPNPrimeData = rpn.preparePrimeData:__main__',
'testRPN = rpn.testRPN:__main__',
],
}
专家可能需要更多细节,我很乐意提供这些细节,当然,整个项目都可以从GitHub获得。这个项目相当庞大,有点令人费解......它超出了我管理Python项目的能力,因为它对我来说只是一种爱好,我在日常工作中做C ++。
感谢您的帮助。
答案 0 :(得分:1)
对于您的项目的特定情况,您已在每个模块中定义了main
函数,因此要使setuptool入口点正常工作,您可以直接引用它们,就像您导入它们一样(import makeUnits
),即:
entry_points = {
'console_scripts': [
'rpn = rpn:main',
'makeRPNHelp = makeHelp:main',
'makeRPNUnits = makeUnits:main',
...
]
}
为什么您可能对需要__main__
感到困惑的是,如果这是可执行脚本,则将此值分配给模块__name__
,或者将模块命名为__main__.py
是一种方式允许在命令行上使用python -m example.module
直接执行模块(pip
for instance does this python -m pip
工作)。但是,对于标准入口点,只需直接引用module:attr
,它应该按预期执行。
另外,请考虑浏览Python网站上的documentation about packaging,因为它将解决how to properly package a project(正如您所注意到的那样,setuptools文档实际上并未教授)。还要考虑创建一个名为rpn
的目录,并将你的rpn * .py文件放到那里,以便更好地将你的程序代码组织到它自己的命名空间中(这样就可以像你最初定义的那样创建入口点(例如makeHelp = rpn.makeHelp:main
工作;当然这会改变主要功能的导入方式(from rpn.makeHelp import main
),但我注意到在PyPI(官方python包索引)上已经存在rpn
package。