How do I get the current topmost package, i.e., the name defined in setup.py?
Here is my tree
:
.
|-- README.md
|-- the_project_name_for_this_pkg
| |-- __init__.py
| |-- __main__.py
| |-- _config
| | `-- foo.conf
| |-- _data
| | `-- logging.yml
| `-- tests
| |-- __init__.py
| `-- test_foo.py <--- # executing from here
|-- requirements.txt
`-- setup.py
4 directories, 9 files
The only solution I've gotten to work so far is this:
import os
import sys
os.path.basename(sys.path[1])
But this is obviously a bad solution. Other solutions like having a __name__
in my uppermost __init__.py
file and using ast.parse
to read in the relevant section of setup.py
also seems cumbersome.
Other solutions I've tried—by calling them within a unittest.TestCase
inheriting class
in my tests
python [sub]package—include checking sys.modules[__name__]
, inspect.getmodule
& inspect.stack
, as well as the answers to these questions:
BTW: In case you were wondering why I want the package name… it's so I can run things like:
import pkg_resources
version = pkg_resources.require('the_project_name_for_this_pkg')[0].version
data_file = path.join(resource_filename('the_project_name_for_this_pkg', '__init__.py'),
'_config', 'data_file.txt')
Not entirely sure what the larger goal is, but maybe you could be interested in reading about importlib.resources
as well as importlib.metadata
.
Something like the following:
import importlib.metadata
import importlib.resources
version = importlib.metadata.version('SomeProject')
data = importlib.resources.files('top_level_package.sub_package').joinpath('file.txt').read_text()
And more generally, it is near impossible (or not worth the amount of work) to 100% reliably detect the name of the project (SomeProject
) from within the code. It is easier to just hard-code it.
Nevertheless here are some techniques, and ideas to retrieve the name of the project from one of its modules:
Update:
I believe some function like the following should return the name of the installed distribution containing the current file:
import pathlib
import importlib_metadata
def get_project_name():
for dist in importlib_metadata.distributions():
try:
relative = pathlib.Path(__file__).relative_to(dist.locate_file(''))
except ValueError:
pass
else:
if relative in dist.files:
return dist.metadata['Name']
return None
Update (February 2021):
Looks like this could become easier thanks to the newly added packages_distributions()
function in importlib_metadata
:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With