1

I'm currently working on a program, which looks through a given python file, resolves all imports, and adds them to a "loader" of sorts, that ensures that the dependencies are there, before actually running the underlying program.

There's one issue: Sometimes, import names do not match the actual package name that has to be installed.

Is there a good way to resolve import names to their package names?

Additional info: The packages to search for will be installed on the disk, if that helps somewhat.

Thanks.

0x150
  • 589
  • 2
  • 11
  • https://stackoverflow.com/a/43808895/7976758 Found in https://stackoverflow.com/search?q=%5Bpython%5D+find+import+package – phd Sep 28 '22 at 15:39
  • Does this answer your question? [How to find "import name" of any package in Python?](https://stackoverflow.com/questions/7184375/how-to-find-import-name-of-any-package-in-python) – ms12 Sep 28 '22 at 15:39
  • @phd The question answered there is in the reverse order I'm trying to go. I am trying to resolve the package name in exchange for the import name – 0x150 Sep 28 '22 at 15:58
  • @Skipper At the linked answer there is the last part "**Reverse look up**" that says "No simple way". My advice would be to collect all top-level modules of all installed wheels and from the list do the reverse lookup. – phd Sep 28 '22 at 16:18

1 Answers1

1

Found it out myself, turns out that pkg_resources.working_set contains all installed projects currently available. From there on out, I was able to kind of figure out which imports a project provides, and worked backwards through the list.

My current code looks like this:

def to_package_list(imports):
    pkg_map = {}
    all_packages: pkg_resources.WorkingSet = pkg_resources.working_set
    for package in all_packages:
        p: pkg_resources.Distribution = package
        f = os.path.join(
            p.location,
            f"{p.project_name.replace('-','_')}-{p.version}.dist-info",
            "RECORD",
        )
        if os.path.exists(f) and os.path.isfile(f):
            with open(f, "r") as file:
                lines = file.read().splitlines()
                imported_names = [x.strip().split("/")[0] for x in lines]
                filtered_imported_names = []
                for n in imported_names:
                    if "." not in n and n not in filtered_imported_names:
                        filtered_imported_names.append(n)
                for n in filtered_imported_names:
                    pkg_map[n] = p.project_name
    return [{"proj": pkg_map[x] if x in pkg_map else x, "imp": x} for x in imports]

This seems to work relatively well. If anyone else has better solutions than this, please let me know.

0x150
  • 589
  • 2
  • 11
  • I'm not convinced that what you are doing is a good idea, but nice job finding an answer anyway. I mean that can often help to find the package, but I would not trust it for all cases. – antont Sep 28 '22 at 18:11