I wrote a Python 3 console-application which has the same structure as the example below. I want to know how I should be importing the modules in order to achieve the behavior specified in the desired functionality section.
/foo
|-/foo
| |-__init__.py
| |-/bar
| | |-__init__.py
| | |-eggs.py
| |-ham.py
| |-spam.py
|-setup.py
Where:
- The
spam
module has themain
function - The
spam
module imports the Ham class in theham
module - The
ham
module imports the Egg class in theeggs
module - Both
__init__.py
files are empty - Basic
setup.py
file that importssetuptools
Desired Functionality
I want to be able to upload the console app to PyPi. Then it can be downloaded as a package with
pip
, and be executed in the terminal.~/>> foo
I also want to be able to run it as a Python script.
~/foo>> python3 foo/spam.py
I found, what I think is a hacky, way to achieve this.
The (hacky) Solution
In order to get the installed package and Python script functionality, I added a try: ... except: ...
which works but it doesn't seem the right way to do this.
try:
from module import Class # import will work for running as script
except:
# relative import will work for running as a package installed with pip
from .module import Class
If I only leave the relative import, and try to run the code as a Python script, I get:
Traceback (most recent call last):
File "foo/spam.py", line 6, in <module>
from .ham import Ham
ModuleNotFoundError: No module named '__main__.ham'; '__main__' is not a package
A similar situation occurs if I leave the regular import and run console application:
Traceback (most recent call last):
File ".../foo/spam.py", line 6, in <module>
from ham import Ham
ModuleNotFoundError: No module named 'ham'
The Files
__init__.py
files are empty
spam.py
"""spam module"""
try:
from ham import Ham
except:
from .ham import Ham
def main():
pass
if __name__ == "__main__:
main()
ham.py
"""ham module"""
try:
from eggs import Egg
except:
from .eggs import Egg
class Ham:
pass
eggs.py
"""eggs module"""
class Egg:
pass
setup.py
from setuptools import setup, find_packages
setup(
name="foo",
version="1.0.0",
author="Pablo",
description="Example",
packages=find_packages(),
entry_points={
"console_scripts": ["foo=foo.spam:main"]
},
)