Skip to main content

Change the message in ModuleNotFoundError

Project description

friendly_module_not_found_error

Windows PowerShell 2025_8_10 21_54_12

This is a Python package that provides the monkey patch for handling module not found errors in a friendly way. When you spell a module name incorrectly, the package will change the exception with a friendly message and suggestions for the possible correct module name.

Installation

To install the package, run the following command:

pip install friendly_module_not_found_error

Usage

Don't need to import the packages. The pth file is already in the site-packages folder named "friendly_module_not_found_error.pth". Any using for the module in your programs are undocumental behavior(UB).

You can use the code to test the effects of the package:

import ant

The message raised will change to : "No module named 'ant'. Did you mean 'ast'?" The suggestion may be change according to the packages you have installed.

import multiprocessing.dumy

The message raised will change to : "module 'multiprocessing' has no child module 'dumy'. Did you mean 'dummy'?"

You can also run "testmodule" to test the effects of the python.

If there is not "friendly_module_not_found_error.pth" in the "site-packages" folder, you can add the file to the "site-packages" folder and add the following code to the file:

import friendly_module_not_found_error

On linux (or if the ".pth" file doesn't work), you can add "sitecustomize.py" to the "site-packages" folder of the python and add the code above.

When uninstall the package, you need also to remove the file above.

Example

Effect and explain

The example:

import xxx.yyy.zzz

If "xxx" not exist, the message is: "No module named 'xxx'" If "xxx" exist but "yyy" not exist, the message is: "module 'xxx' has no child module 'yyy'" Then the message add like the text below: The final name will be compared to all module at that path. If at the top, it first compared with stdlib and then compared with the path in sys.path. Or, if the module before is not a package and the now module not exist, the message will add "module '...' is not a package". For the non-package module, it won't support for this condition: module has a child module, and it has child module. For package, it will scan the attribute "__path__" to get all possible child module to compare.

The change can clearly show the specific error in import and give the near name suggestion. For example, the original is "No module named 'xxx.yyy.zzz'", we cannot get message that which step is wrong, now we can see which step is wrong: "No module named 'xxx'" means the top, "module 'xxx' has no child module 'yyy'" means the second, and ''module 'xxx.yyy' has no child module 'zzz'" means the third, and so on. And like NameError and AttributeError, it will suggest the possible name.

Require

python3.7+

In friendly_module_not_found_error verison 0.4.2, it supports python3.7+.

License

This package is licensed under the MIT License. See the LICENSE file for more information.

issues

If you have any questions or suggestions, please open an issue on GitHub.

Contributing

Contributions are welcome! Please submit a pull request with your changes.

Data

The test for "__main__.py" here:

No. number of entries used time(/s) average time(/s) result
1 5 0.064 0.013 success
2 5 0.072 0.014 success
3 5 0.052 0.010 success
4 5 0.056 0.011 success
5 5 0.057 0.011 success
6 6 0.081 0.014 success
7 6 0.062 0.010 success
8 6 0.091 0.015 success
9 6 0.064 0.011 success
10 6 0.064 0.011 success

The speed test here:

tool function arg number average time(/ms)
timeit find_all_packages (no args) 1000 8.567
timeit scan_dir path/to/site-packages 1000 4.845

The function "find_all_packages" defined here:

def find_all_packages() -> list[str]:
    """
    Find all packages in the given path.
    If top is True, return all top packages.
    """
    return sorted(sum([scan_dir(i) if
                isinstance(i, str) else []
                for i in sys.path ], []) + 
                list(sys.builtin_module_names))"

Note

If a module that is not a package contains submodules, and those submodules also contain their own submodules, this nested module structure is not supported. When this situation occurs, you should reorganize the code using proper package structure. This approach violates Python's packaging best practices and should be avoided.

To make your custom import hook be supported, you need to define a magic method "__find__" to return the list of all modules. For example:

class MyImportHook:
    def __find__(self, name: str=None) -> list[str]:
        """
        Return a list of all modules that are available to the import hook without import them.
        If the "name" is provided, the method should return a list of all submodules that under the module named "name".
        parameter name: The name of the module to find submodules for. If None, return all top modules.
        """
        return []

The "__find__" method should return a list of all modules that are available to the import hook without import them. If the "name" is provided, the method should return a list of all submodules that under the module named "name". Or it needs to return all top modules if the "name" is None. The name should be the full name of the module, such as:

topmodule/
    __init__.py
    subpackage/
        __init__.py
        submodule/
            __init__.py
            nonpackage.py

The name of the top module is "topmodule", the name of the subpackage is "topmodule.subpackage", and the name of the submodule is "topmodule.subpackage.submodule".

Warning

When your code raises the "ModuleNotFoundError", if there is the suggestion given by the package, you need to check it. Anyway, if your IDE suggests you to pip install the wrong name module, check it instead of following it blindly. It may be a malicious package.

Rejected suggestion

  • Build a cache for site-packages when install: The code runs fast, so it can find all of the packages fast. Before that finding costs, the computer has been almost broken.
  • Suggest for "pip install xxx": spelling mistakes are often closely associated with homograph attacks. Suggesting for it will help the attacker.

Credits

This package was created by Locked-chess-official and is maintained by Locked-chess-official

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

friendly_module_not_found_error-1.0.1.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

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

File details

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

File metadata

File hashes

Hashes for friendly_module_not_found_error-1.0.1.tar.gz
Algorithm Hash digest
SHA256 afb470401521c9ad94d6af9228bd73eb8651ddc1aa8d07c74e820f29a14d3d4b
MD5 e883748252104bd716b54053e9e90861
BLAKE2b-256 b21ee19247330dc4d45cb7566ac525d091458994a5ca6444c148c225df8f557a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for friendly_module_not_found_error-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2178148f1802bf783d24283b37292a8ef35f29317f8b6cd7f6996faf5c1bd2c1
MD5 1aca72d4ecce3047bb015a8184fa414c
BLAKE2b-256 5d3cdfe7079e8087377f9e1b5e4cafeb5a8c8272a01131246314902c85314a2c

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