I have this CLI tool called Rackfocus. I've published to PyPI, and I'm reasonably sure it worked just fine before. When I try to run it with current versions of Python on Mac, I get the error:
No module named rackfocus.__main__; 'rackfocus' is a package
and cannot be directly executed
All I want is one package with one entry point that users can download and use using pip.
Based on tutorials, I have this in setup.py:
packages=['rackfocus']
entry_points = {
'console_scripts': [
'rackfocus=rackfocus.run:main'
]
}
And I have a rackfocus.run:main
function, an init.py and everything. What's wrong?
You can reproduce this locally:
pip3 install -e .
python3 -m rackfocus
entry_points = {
'console_scripts': [
'rackfocus=rackfocus.run:main'
]
}
This tells the packaging system to create a wrapper executable named rackfocus
. That executable will automatically handle all the necessary steps to get Python off the ground, find the run
module in the rackfocus
package, find its main
function and call it.
You run the executable like rackfocus
(if you are using a virtual environment, it should be on the path already), not python -m rackfocus
.
Using python -m rackfocus
is completely unrelated to that (it doesn't even have anything to do with packaging, and can easily be used with code that hasn't been installed yet). It doesn't use the wrapper; instead, it simply attempts to execute the rackfocus
module. But in your case, rackfocus
isn't a module; it's a package. The error message means exactly what it says.
You would want python -m rackfocus.run
to execute the run
module - but of course, that still doesn't actually call main()
(just like it wouldn't with python rackfocus/main.py
- though the -m
approach is more powerful; in particular, it allows your relative imports to work).
The error message says rackfocus.__main__
because you can make a package runnable by giving it a __main__
module.