Reputation: 37081
I'm a Ruby programmer working on my first Python package (let's call it foo). Its primary purpose is as a command line tool. I'm specifying that it should be installed as an executable in setup.py
using:
setup(
entry_points={
'console_scripts': [
'foo = foo.cli:main'
]
}
)
foo/cli.py
contains:
import foo
def main():
# program logic here
if __name__ == '__main__':
main()
cli.py
needs to reference foo.__version__
which is defined in foo/__init__.py
, but when I run python foo/cli.py
locally to test the CLI, import foo
raises ImportError: No module named foo
. How do I get Python to see cli.py in the context of the foo package when running an individual file like this? Is my approach totally wrong? How do you normally go about testing an executable defined with setuptools's entry points locally?
Upvotes: 1
Views: 231
Reputation: 4767
You are missing modifying the sys.path
or PYTHONPATH
variable to also include the directory where foo/ resides.
On the command prompt before you run the cli.py file do the following
codepython@vm-0:~/python/foo$ PYTHONPATH=$PYTHONPATH:~/python/;export PYTHONPATH
Here in my setup foo/ is present within ~/python and the presence of _init_.py within foo/ tells the python interpreter that foo is a package and not an ordinary directory.
Now you can cd
into the foo/ directory and then run python cli.py
. You will be able to access the foo package methods and functions.
Alternatively within main() you can first modify the sys.path
to append the directory containing foo/ and then perform rest of the logic
To quote Python documentation on Modules:
When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:
the directory containing the input script (or the current directory). PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH). the installation-dependent default. After initialization, Python programs can modify sys.path. The directory containing the script being run is placed at the beginning of the search path, ahead of the standard library path. This means that scripts in that directory will be loaded instead of modules of the same name in the library directory. This is an error unless the replacement is intended. See section Standard Modules for more information.
Upvotes: 1
Reputation: 1421
Within the package, you can directly import __init__
and then rename with as
. Try this
import __init__ as foo
in place of
import foo
Upvotes: 1