Skip to main content

A Python package for various lazy (discouraged) import strategies.

Project description

bumimport

License: GPL v3

So you're about to append to sys.path in order to import something when a Neckbeard on Stack Overflow tells you it's "bad practice"...

Well, the Neckbeard is right, and you probably should learn how to use the import system properly. However, if you insist on being a Bum, here's a safer alternative.


You might be tempted to append to sys.path so that you can import a module from another directory like importing module1 in main.py in the example below.

├── main.py
├── bucket_o_modules/
│   ├── module1.py
│   ├── module2.py

Of course, you can just add __init__.py to bucket_o_modules/ so that you can import module1 from bucket_o_modules in main.py.

├── main.py
├── bucket_o_modules/
│   ├── __init__.py
│   ├── module1.py
│   ├── module2.py

However, this only works when main.py and bucket_o_modules/ are in the same package. Not to mention, a more complicated file structure would require you to add __init__.py to every subdirectory.

├── main.py
├── bucket_o_modules/
│   ├── __init__.py
│   ├── module1.py
│   ├── extra_special_modules/
│      ├── __init__.py
│      ├── module2.py

This has its own downsides. module1 and module2 now have to be imported from different packages, bucket_o_modules and bucket_o_modules.extra_special_modules, respectively. You can get arround this by adding code within each __init__.py to "pull up" each of the modules into each package's parent package, but by now you can probably see this is getting tedious, and it would be annoying to maintain as the contents of bucket_o_modules/ change.


This is where bumimport comes into play.

Instead of using the following code to import any module from bucket_o_modules/:

import importlib
import sys

sys.path.append("/path/to/bucket_o_modules/")

mod = importlib.import_module("module1")

Use the following:

import sys

import bumimport

bumimport.flat_import(__name__, "/path/to/bucket_o_modules/")

mod = getattr(sys.modules[__name__], "module1")

flat_import adds all the modules within bucket_o_modules/ to the module __name__ (the current module) as attributes. Those attributes can then be accessed with getattr().

Likewise, instead of using the following code to import any module from bucket_o_modules/ or any of its subdirectories:

import importlib
import os
import sys

for root, _, _ in os.walk("/path/to/bucket_o_modules/"):
    sys.path.append(root)

mod = importlib.import_module("module1")

Use the exact same code as before:

import sys

import bumimport

bumimport.flat_import(__name__, "/path/to/bucket_o_modules/")

mod = getattr(sys.modules[__name__], "module1")

bumimport really thrives when you use it in a single __init__.py in the root of a package. Consider the following file structure:

├── main.py
├── bucket_o_modules/
│   ├── __init__.py
│   ├── module1.py
│   ├── extra_special_modules/
│      ├── module2.py

If __init__.py contains the following:

from bumimport import flat_import as _flat_import

_flat_import(__name__, __file__)

Then the following code can be used in main.py:

import bucket_o_modules

mod1 = getattr(bucket_o_modules, "module1")
mod2 = getattr(bucket_o_modules, "module2")

Now you can access the modules in bucket_o_modules/ as if it was a flattened package. Additionally, modules with invalid names like os, mod.ule1, or mod-ule1 can still be accessed (getattr() required for any name that breaks dot notation).


bumimport is safer because it never modifies sys.path which means there is no risk of modules getting masked. It also prevents any module with the same name as an existing attribute from being added which means there's no confusion over which module you end up having access to. Lastly, the imported modules are never added to sys.modules which means there will never be conflicts with the standard library.

Installation

  • With pip:

      pip install bumimport
    

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bumimport-1.1.0.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bumimport-1.1.0-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file bumimport-1.1.0.tar.gz.

File metadata

  • Download URL: bumimport-1.1.0.tar.gz
  • Upload date:
  • Size: 17.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.3

File hashes

Hashes for bumimport-1.1.0.tar.gz
Algorithm Hash digest
SHA256 4f909f40884e5789f2fdd76a969b1d013151fde57037426ea684d1da5d5f23eb
MD5 6bd935b56c3e187be5135d1ac774e6be
BLAKE2b-256 a1f15cf817a18790cb063c8b344ed934b4133ad4e8fc81a670c40037bfe9e95d

See more details on using hashes here.

File details

Details for the file bumimport-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: bumimport-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.3

File hashes

Hashes for bumimport-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd0fe35e9a81dbdc927276493ed7d090556167c466b64d8cdd657d1a35d24793
MD5 255e915e394a60ab8131c58e7d4db314
BLAKE2b-256 23078de18b6c4624f79c26e3d35fd63b7cda368621fe10a9000efa5f4c991c54

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page