Python 从 py 模块中读取所有导入语句的简单方法 [英] Python easy way to read all import statements from py module

查看:58
本文介绍了Python 从 py 模块中读取所有导入语句的简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个辅助函数来读取文件并模拟单元测试的所有导入.我必须阅读文件与导入,因为我在 python 路径上没有这些东西.

示例代码:

<小时>

#module.py导入 com.stackoverflow.question从 com.stackoverflow.util 导入 test_func从 com.stackoverflow.util 导入 TestClass

<小时>

#magic helper: 我想要什么magic = process('<path_to>/module.py')对于 magic.modules_as_strings() 中的模块:#todo 必须递归地添加每条路径# 所以我会先创建 com,然后是 com.stackoverflow,等等setattr(自我,模块,StubModules(模块)对于magic.sink中的obj:#这些将是from" from x import Y#它基本上只是创建 self.Y = objectsetattr(自我,对象)

以上是模拟代码,我真的在寻找将文件标记为from/import 语句"的最佳方法

这有道理吗?我知道我可以逐行读取文件,但我希望有一种更清晰/简洁的方式.

如果您有任何问题,请告诉我.

解决方案

使用 AST 模块,很简单:

导入 ast从集合导入namedtupleImport = namedtuple("Import", ["module", "name", "alias"])def get_imports(路径):使用 open(path) 作为 fh:root = ast.parse(fh.read(), 路径)对于 ast.iter_child_nodes(root) 中的节点:如果 isinstance(node, ast.Import):模块 = []elif isinstance(node, ast.ImportFrom):模块 = node.module.split('.')别的:继续对于 node.names 中的 n:产量导入(模块,n.name.split('.'),n.asname)

对于这样的模块:

from coco import bunny从 coco.bungy 进口胡萝卜从元导入 teta从火箭进口飞船作为sp进口宾果导入 com.stackoverflow进口摩托车作为汽车导入模块 1、模块 2s="一个随机变量"定义函数():"""还有一个函数"""

输出为:

<预><代码>>>>对于 get_imports("/path/to/file.py") 中的imp:打印imp导入(模块=['coco'],名称=['bunny'],别名=无)导入(模块=['可可','蹦极'],名称=['胡萝卜'],别名=无)导入(模块=['meta'],名称=['teta'],别名=无)导入(模块 = ['火箭'],名称 = ['太空船'],别名 ='sp')导入(模块=[],名称=['bingo'],别名=无)导入(模块=[],名称=['com','stackoverflow'],别名=无)导入(模块=[],名称=['摩托车'],别名=汽车")导入(模块=[],名称=['module1'],别名=无)导入(模块=[],名称=['module2'],别名=无)

I am trying to create a helper function to read a file and mock out all imports for a unit test. I have to read the file vs import since i dont have those things on python path.

Example code:


#module.py
import com.stackoverflow.question
from com.stackoverflow.util import test_func
from com.stackoverflow.util import TestClass


#magic helper: what i want
magic = process('<path_to>/module.py')
for module in magic.modules_as_strings():
    #todo  would have to recuirsively add each path
    # so i would first create com, then com.stackoverflow, etc
    setattr(self, module, StubModules(module)
for obj in magic.sink:
    #these would be "from"  from x import Y
    #its basically just creating self.Y = object
    setattr(self, object)

Above is the mock code, I am really looking for the best way to just tokenize the file for "from/import statements"

That make sense? I know I could read the file line by line, but I was hoping for a cleaner/concise way.

Let me know if you have any questions.

解决方案

Using the AST module, it is pretty easy:

import ast
from collections import namedtuple

Import = namedtuple("Import", ["module", "name", "alias"])

def get_imports(path):
    with open(path) as fh:        
       root = ast.parse(fh.read(), path)

    for node in ast.iter_child_nodes(root):
        if isinstance(node, ast.Import):
            module = []
        elif isinstance(node, ast.ImportFrom):  
            module = node.module.split('.')
        else:
            continue

        for n in node.names:
            yield Import(module, n.name.split('.'), n.asname)

For a module like this:

from coco import bunny
from coco.bungy import carrot
from meta import teta
from rocket import spaceship as sp
import bingo
import com.stackoverflow
import motorbike as car
import module1, module2

s="a random variable"

def func():
    """And a function"""

The output is:

>>> for imp in get_imports("/path/to/file.py"): print imp
Import(module=['coco'], name=['bunny'], alias=None)
Import(module=['coco', 'bungy'], name=['carrot'], alias=None)
Import(module=['meta'], name=['teta'], alias=None)
Import(module=['rocket'], name=['spaceship'], alias='sp')
Import(module=[], name=['bingo'], alias=None)
Import(module=[], name=['com', 'stackoverflow'], alias=None)
Import(module=[], name=['motorbike'], alias='car')
Import(module=[], name=['module1'], alias=None)
Import(module=[], name=['module2'], alias=None)

这篇关于Python 从 py 模块中读取所有导入语句的简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆