Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

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

I am having python files with the import statements which I would like to replace into the actual code placed in the foo.py.

For instance, with the in file:

from foo import Bar

bar = Bar()
print bar

I would like to out file below:

# source of Bar class.

bar = Bar()
print bar

How can I perform such imports replacement ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I suggest you to use the ast.NodeTransformer in order to accomplish such import replacement.

AST provides way to interact with the python code as with the trees of the Python abstract syntax grammar.

The ast.NodeTransformer can be used to traverse through your code and identifying ImportFrom node ( the code parsed with ast is represented as the tree of nodes). After identifying ImportFrom node you can replace it with group of nodes which correspond to the source code of the Bar class, which lead to your goal.

Please see code below which describes approach described below:

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)

NOTE 1: I suggest you to use the exec in order to compile sources with correct globals and locals dict.

NOTE 2: Take into account that you will need to handle nested imports ( if foo file stores imports you wish to replace to).

NOTE 3: I've used astor to convert code from ast tree into the python code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...