Printing Python Imports

In my last post, Tips For Pinning Python Requirements Files, I touched briefly on import discovery. I used grep as a crude mechanism to grab python import because it’s Good Enough™. Bash scripts are a great way to get started, but sometimes one requires a more robust tool. I’ve since spent some time diving deeper into the Python import system and discovered a better solution. Let’s start with a single file named We’ll give it a couple of different import flavors to run the gambit.

import requests
from requests import RequestException, HttpError
from requests.api import sessions

r = requests.get("")

To understand the structure of this script, we can use Python’s ast module The ast module helps Python applications to process trees of the Python abstract syntax grammar. We can build a separate script (called that will print all the imports it finds:

#!/usr/bin/env python3

import ast
import inspect
import importlib
import sys

class MyNodeVisitor(ast.NodeVisitor):

    def __init__(self):
        self.imports = set()

    def visit_Import(self, node):
        for module_node in node.names:
            self.imports.add(f"import {}")

    def visit_ImportFrom(self, node):
        module_name = node.module
        for from_node in node.names:
            self.imports.add(f"from {module_name} import {}")

# Consider all arguments passed to be filepaths
for file_path in sys.argv[1:]:
    with open(file_path, "r") as f:
        contents =
        mod_ast = ast.parse(contents)
        visitor = MyNodeVisitor()
        for import_line in visitor.imports:

NodeVisitor is part of the ast module. Each time it visits a certain node it will call the function import_<Class>. We’re looking for both Import and ImportFrom. visit_Import will grab lines that look like import requests. visit_ImportFrom will grab lines that look like from requests import RequestException. Once we’ve grabbed all the imports, we print them. Make sure you run chmod +x before running the following:

$ ./

But, what about multiple python files? We could build logic to traverse directories and grab files in python, but I’ll leave that to bash. By accepting a list of paths via sys.argv[1:], we can can use find and xargs do the lifting.

$ find ~/path/to/pythonfiles -name '*.py' -print0 | xargs -0 ./ | sort | uniq

This approach works out cleaner than the previous post’s grep example. Each import is printed on a separate line so we don’t have to worry about brackets. The python script does one thing, print imports of a single file. I prefer using bash tools to handle finding/filtering files. One more handy tool in your toolkit.