0

I used PyScaffold to create a template for a PyPi package I am creating, bbox-utils. The generated __init__.py is as follows:

from pkg_resources import DistributionNotFound, get_distribution

try:
    # Change here if project is renamed and does not equal the package name
    dist_name = "bbox-utils"
    __version__ = get_distribution(dist_name).version
except DistributionNotFound:  # pragma: no cover
    __version__ = "unknown"
finally:
    del get_distribution, DistributionNotFound

I'm a bit confused what name to use for dist_name. I tried doing:

>>> from pkg_resources import DistributionNotFound, get_distribution
>>> get_distribution('bbox_utils').version
'0.0.1'
>>> get_distribution('bbox-utils').version
'0.0.1'

and I get the same version whether I replace the hyphen with an underscore or leave it as is. Which should I do?

Edit: Here is the GitHub repo Here is PyPi link

Eric Wiener
  • 4,929
  • 4
  • 31
  • 40

1 Answers1

2

You generally should not name your packages or modules using dashes although you can. Since the import statement does not use quotes, using a dash is interpreted as using a minus sign, which will result in an illegal syntax during import if using the dash name.

There are ways around this, such as importing with underscores but installing via pip/searching pypi with dashes, but it is a needless inconsistency that can cause frustration. Generally the python approach is to be able to import modules as valid module objects whose variable name equals the actual module name. When naming projects, it is therefore better to use underscores instead of dashes.

That being said, pkg_resources seems to actually replace all non-alphanumeric and non-dot characters with dashes when resolving project names.

assert(get_distribution('bbox_utils').project_name == 'bbox-utils')
assert(get_distribution('bbox-utils').project_name == 'bbox-utils')

So you should be able to use either expression interchangeably in the code snippet in the question.

Matt Miguel
  • 1,325
  • 3
  • 6
  • `get_distribution(dist_name.replace('-', '_'))` – phd Jan 12 '21 at 12:32
  • 1
    Thanks for the response. My package is imported as `bbox_utils`, but called `bbox-utils` on PyPI (I added links to the question). Why does the same version get returned using the distribution name with a hyphen and with an underscore? And since they both work, which should be returned? It is valid syntax, so this doesn't really answer there question – Eric Wiener Jan 12 '21 at 13:11
  • 1
    @EricWiener The pkg_resources module actually replaces all non alphanumeric and dot characters with dashes when producing their project name variables. So get_distribution('bbox_utils').project_name will be equal to 'bbox-utils' - you can use either. My answer was about using underscores in your actual project name vs this snippet. This is because you make everyone have to do an extra mental translation step in figuring out how to import your script after installing, or installing it on another computer after they are used to importing it with underscores. Needless inconsistencies aren't good. – Matt Miguel Jan 12 '21 at 16:42
  • @MattMiguel thanks for the clarification! That helps a lot. I looked at the [most common](https://hugovk.github.io/top-pypi-packages/) Python packages and quite a lot of them using hyphens in the name. Are you saying not to use hyphens in the PyPI name or the name that the package is imported with `import bbox_utils`? – Eric Wiener Jan 12 '21 at 18:30
  • 1
    @EricWiener Yes it is fairly common. My opinion/answer is motivated by in general not wanting to remember both a project name and a package name. I see lots of posts saying using hyphens is against the PEP8 style guide. However I didn't see anything about that in there. The closest thing I found is in PEP 423 in the "single name" principle, which is similar to my argument - try not to have a different project name vs a package name. Since package names can't really contain hyphens, it's best for project names to not either. Doesn't seem like this is universally followed de facto. – Matt Miguel Jan 12 '21 at 21:24
  • @MattMiguel got it. Thanks so much for the help! – Eric Wiener Jan 12 '21 at 21:32
  • This hyphen-to-dot replacment went a bit too far - [according to `semver`](https://github.com/semver/semver/blob/a4f21e1a6fdf7d1a78a2d965889d958f96b11b42/semver.md?plain=1#L93) _pre-release versions denoted by appending a hyphen_ while a call to `get_distribution("argrelay").version` will replace hyphens to dots (even in version numbers)! – uvsmtid Mar 06 '23 at 14:29