Search code examples
pythonpippython-importpypipython-packaging

PyPI - allow importing a module using a different name


Edit a year later:
I have no idea why this post wasn't closed as I was completely ignorant about the proper package structure for a python package :)
For anyone wondering, I was setting up my project completely wrong. Moral of the story - read the docs for how to do it, don't just try to 'wing it'!

I recently created a simple python package / library and uploaded it to (PyPI). That's all fine - I can upload my project to pypi and download it again using pip, but I can't import it because it contains a full stop .

My package is called dcode.py (which obviously causes issues with importing), I'd like to be able to import it by just typing import dcode (without the .py). I've looked around for a solution but can't seem to find one - I'd like to be able to import it under an alias (dcode) instead of dcode.py (which obviously doesn't work).

Is there a way to do this? I'd assume there must be (for example, both the packages discord.py and py-cord can both just be imported using import discord. Does anyone know how to do this?

Just in case you need it, my pyproject.toml file looks like this:

[project]
name = "dcode.py"
version = "0.0.2"
authors = [
{ name = "Dylan Rogers", email = "opendylan@proton.me" },
]
description = "dcode - the Python package for everything"
readme = "README.md"
requires-python = ">=2.0"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
"Homepage" = "https://github.com/dylanopen/dcode.py"
"Bug Tracker" = "https://github.com/dylanopen/dcode.py/issues"

And my entire project is on github. Here is the PyPI project

I've tried importing dcode.py:

import dcode.py

But I just get this error:

File "/run/media/dylan/Programming/dcode.py-test/test.py", line 1, in <module>
    import dcode_py
ModuleNotFoundError: No module named 'dcode_py'

If it helps, I'm using Manjaro Linux (no idea why it would help though, I just need to know how to allow users to import dcode.py by typing import dcode, like they import discord.py as discord)

Thank you so much for any help!


Solution

  • This is the recommended directory structure your project should have:

    dcode.py/
    ├── LICENSE
    ├── pyproject.toml
    ├── README.md
    ├── src/
    │   └── dcode/
    │       ├── __init__.py
    │       └── io/
    │           ├── __init__.py
    │           └── file.py
    └── tests/
    

    Here dcode (as defined by dcode.py/src/dcode) is the name of the only top-level importable package. And it also contains a sub-package dcode.io (as defined by dcode.py/src/dcode/io).

    The name of the actual distribution project as seen on PyPI and that gets pip-installed is defined in the package metadata, in the pyproject.toml file:

    [build-system]
    requires = ["setuptools>=61.0"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "dcode.py"
    version = "0.0.1"
    authors = [
      { name = "Dylan Rogers", email = "opendylan@proton.me" },
    ]
    description = "dcode - the Python package for everything"
    readme = "README.md"
    requires-python = ">=3.8"
    
    [project.urls]
    "Homepage" = "https://github.com/dylanopen/dcode.py"
    "Bug Tracker" = "https://github.com/dylanopen/dcode.py/issues"
    
    [tool.setuptools.packages.find]
    where = ["src"]
    

    Do not push the dist directory containing the built sdist and wheel distribution packages artifacts into the source code repository.

    Do not push any *.egg-info directory into the source code repository.

    Place all the actual Python code inside a src directory.

    The name of the project can contain a dot such as dcode.py, although I would recommend against it.

    The name of the actual top-level import packages and modules can be completely different than the name of the distribution project.

    If you declare a classifier for the license in the package metadata in pyproject.toml, then it should match the actual license file in the source code repository (you had a GNU GPL v3.0 license file but a MIT license classifier).

    References: