有没有办法用实际来源替换 python 导入?

Is there are a way to replace python import with actual sources?

我有 python 个包含导入语句的文件,我想将其替换为 foo.py 中的实际代码。

例如,对于 in 文件:

from foo import Bar

bar = Bar()
print bar

我想要out以下文件:

# source of Bar class.

bar = Bar()
print bar

如何执行此类导入替换?

我建议你使用 ast.NodeTransformer 来完成这样的导入替换。

AST 提供了与 python 代码交互的方式,就像与 Python 抽象句法文法树交互一样。

ast.NodeTransformer 可用于遍历您的代码并识别 ImportFrom 节点(使用 ast 解析的代码表示为节点树)。识别 ImportFrom 节点后,您可以将其替换为对应于 Bar class 的 源代码的一组节点,从而实现您的目标。

请参阅下面的代码,其中描述了下面描述的方法:

from ast import NodeTransformer, parse, fix_missing_locations

import astor


class FromImportTransformer(NodeTransformer):
    """ General from imports transformer. """


    def visit_ImportFrom(self, node):
        new_node = self.get_sources(node)
        # Replace node.
        fix_missing_locations(node)
        return node

    def get_sources(self, node):
        """ Accepts importFrom node and build new ast tree from the sources described in import. """
        raise NotImplemented


def transform_imports(self, source_file):
    with open(source_file) as original_sources:
        sources = original_sources.read()
    root = parse(sources, source_file)
    try:
        root = FromImportTransformer().visit(root)
    except Exception as exc:
        raise exc
    sources = astor.to_source(root, indent_with=' ' * 4, add_line_information=False)
    return processed_sources


path_to_in_sources = '/tmp/in.py'
path_to_out_sources = '/tmp/out.py'
processed_sources = transform_imports(path_to_in_sources)


with open(path_to_out_sources, 'wb+') as out:
    out.write(processed_sources)

注意 1:我建议您使用 exec 以使用正确的全局变量和局部变量字典编译源代码。

注意 2:考虑到您将需要处理嵌套导入(如果 foo 文件存储了您希望替换为的导入)。

注意 3:我使用 astor 将代码从 ast 树转换为 python 代码。