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.0.1.tar.gz (17.1 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.0.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for bumimport-1.0.1.tar.gz
Algorithm Hash digest
SHA256 3851b486ef9df2f3c1e28457d6060f503cf2cc967e2b7e449ba83a6dd6b8b5aa
MD5 4bca419bb564868cdf96a0135ff30cc5
BLAKE2b-256 2f9aaa47ff88559f1cebadb8589822869d5a99b892cb3cfdbbb292fe7f771d4e

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for bumimport-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2e102fbe5f161655841da956034c25afc7ea9e82c926fe17c5189b38ed2c6a39
MD5 e8d2b78b4c5883ac31e5248f5630f0ac
BLAKE2b-256 53dfffd9540ae651319d9a55a518d441923ae87c8e864c23a20d00143ea8a72c

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