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

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 "hatch_autorun_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.

In version 1.0.6, it provide two api:

  • friendly_module_not_found_error.unchange(): restore the original behavior of the module not found error.
  • friendly_module_not_found_error.rechange(): change the behavior of the module not found error to the friendly way.

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 version 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".

If exception raised in the method "__find__", the exception will be ignored and the default behavior will be used. If the all of the exceptions in the exception chain ("__cause__", "__context__", "BaseExceptionGroup") are not ImportError, it will be printed as warning. Otherwise, the message will be ignored and the module will tips that don't import any modules in the method "__find__".

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 and typosquatting 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.18.tar.gz (17.3 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.18.tar.gz.

File metadata

File hashes

Hashes for friendly_module_not_found_error-1.0.18.tar.gz
Algorithm Hash digest
SHA256 891d1be37feda38e11d607812a01d7eb64bf1b7613ea1de7658f04ef3750b8ea
MD5 7e783515c88d172cce0b9fe554229e97
BLAKE2b-256 80a3ebc35e2645d56c4ae199f21787f90074f8cc82eee2660ee7e4491d0de101

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for friendly_module_not_found_error-1.0.18-py3-none-any.whl
Algorithm Hash digest
SHA256 821e0b1d56a952313e463933bf884984904a9e91bc02ce33e56907e048f0800a
MD5 32bb7af9ddc5e2fdc28f1beebbc3ad49
BLAKE2b-256 fffbceb964c774de7365720244e8a26df2186900f97e8522a683fc14feb8b568

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