最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Python, search from where import is call - Stack Overflow

programmeradmin7浏览0评论

For managing transition from an old import to a new import, I search to log from where my module is used.

By example, my old is name m_old.py. With a simple print in file m_old.py, I display a message "used of old module". So each time there is "import m_old.py", I have a message "used of old module" in execution ?

If it was a function, I will use module inspect and traceback to log in execution from where this function is call, by exemple "call of old function from file.py line XXX".

Is-it possible to display a message like : "this old import is call from file.py line XXX" ?

For managing transition from an old import to a new import, I search to log from where my module is used.

By example, my old is name m_old.py. With a simple print in file m_old.py, I display a message "used of old module". So each time there is "import m_old.py", I have a message "used of old module" in execution ?

If it was a function, I will use module inspect and traceback to log in execution from where this function is call, by exemple "call of old function from file.py line XXX".

Is-it possible to display a message like : "this old import is call from file.py line XXX" ?

Share Improve this question edited Mar 27 at 7:31 Emmanuel DUMAS asked Mar 26 at 12:51 Emmanuel DUMASEmmanuel DUMAS 73911 silver badges28 bronze badges 3
  • if you know the the module is imported you can use module.__file__ to get its path – cards Commented Mar 26 at 13:00
  • Wouldn't it be simpler to just search your codebase for occurrences of import m_old? – John Gordon Commented Mar 26 at 13:24
  • Only the first time. Every subsequent import will see that the module m_old was already created and not execute your code again. – chepner Commented Mar 26 at 13:44
Add a comment  | 

2 Answers 2

Reset to default 1

I have a similar problem: I want to know which module import which library/module, so I wrote a short script:

#!/usr/bin/env python3
"""show_imports.py: Show imports from files"""

import argparse
import ast
from collections import defaultdict
from pathlib import Path

def find_imports(path: Path, found: dict):
    content = path.read_text()
    module = ast.parse(content, path)
    for entity in ast.walk(module):
        if isinstance(entity, ast.Import):
            for alias in entity.names:
                found[alias.name].add((path, entity.lineno))
        elif isinstance(entity, ast.ImportFrom):
            found[entity.module].add((path, entity.lineno))

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("dir")
    options = parser.parse_args()
    root = Path(options.dir).resolve().relative_to(Path.cwd())

    if root.is_file():
        paths = [root]
    elif root.is_dir():
        paths = root.rglob("*.py")
    else:
        raise SystemExit(f"{root} is not a valid dir or file")

    found = defaultdict(set)
    for path in paths:
        find_imports(path, found)

    for mod, paths in found.items():
        print(mod)
        for path, lineno in sorted(paths):
            print(f"  {path}({lineno})")


if __name__ == "__main__":
    main()

You can run this script and pass in either a single python script, or a directory. In the case of directory, all python scripts in there will be analyzed. Here is a sample run of the script against itself:

$ ./show_imports.py show_imports.py
argparse
  show_imports.py(4)
ast
  show_imports.py(5)
collections
  show_imports.py(6)
pathlib
  show_imports.py(7)

Notes

  • I use the ast library to parse each Python script
  • The ast.walk() will walk through all entities in the script, but I only care about the ast.Import and ast.ImportFrom entities

After investigation on module traceback, I found my solution :

traceback.extract_stack()

And analyse list in many level (around 10) and I have found file and line of import.

Can also use inspect, by example like this :

import inspect

fl = inspect.stack()
cnt = 0
for f in fl:
    # print("f=", f.filename, " l=", f.lineno)
    if f.filename[0:7] != "<frozen":
        # print("          >>>>> f=", f.filename, " l=", f.lineno)
        cnt += 1
        if cnt == 2:
            print("WARNING : %s(%d) replace import m_old by import m_new" % (f.filename, f.lineno))
发布评论

评论列表(0)

  1. 暂无评论