如何调用已知其名称为字符串的导入模块?

Art*_*m K 5 python python-import

我正在编写一个应用程序,应该测试许多学生的解决方案。我有这样的结构

app/
    students/
        A/
            lab1/
                solution.py
            lab2
                solution.py
        B/
            lab1/
                solution.py
        C/
    test.py
Run Code Online (Sandbox Code Playgroud)

我想在测试模块中导入解决方案文件并运行 main 方法。我知道有一个__import__函数返回模块对象,但我不知道如何调用 main 方法。

我的代码:

import os


def get_student_names():
    return os.listdir('students')

def test(name, lab):
    if lab not in os.listdir('/'.join(['students',name])):
        return f"{lab} not found"
    if 'solution.py' not in os.listdir('/'.join(['students',name,lab])):
        return "solution file not found"
    module = __import__('.'.join(['students',name,lab,'solution']))
    # module.name.lab.solution.main()

def main():
    student_names = get_student_names()
    for student in student_names:
        result = test(student, "lab1")

Run Code Online (Sandbox Code Playgroud)

我想打电话module.name.lab.solution.main()但是modulestudents。如何切换到solution子模块?

Mic*_*dry 3

您最直接的问题是您没有从testso 返回任何内容,result将永远是None. 您遇到的第二个也是最重要的问题是您实际上没有任何模块。实际上,您有一堆随机文件夹,其中包含任意 python 脚本。这意味着__import__对你来说非常不友好。

如果我们运行这条线

__import__('students.A.lab1.solution').main()
Run Code Online (Sandbox Code Playgroud)

我们得到这个错误:

AttributeError: module 'students' has no attribute 'main'
Run Code Online (Sandbox Code Playgroud)

students?我们应该在solution!这是一个问题。有一种方法可以做到这一点,而不必担心将各个文件夹转换和维护为实际模块。


首先,学生必须提出main他们的解决方案。

前任:

def main():
    print('hello, world')
    
main()
Run Code Online (Sandbox Code Playgroud)

其次,运行他们的脚本。如果命令失败,它会告诉您脚本不存在并继续处理下一个学生。

import os

#change this to however you call python
PY   = 'python3'

#lab format strings
LAB1 = '{} "students/{}/lab1/solution.py"'
LAB2 = '{} "students/{}/lab2/solution.py"'


def main(lab:str) -> None:
    for student in os.listdir('students'):
        os.system(lab.format(PY, student))
            
    
main(LAB1)

Run Code Online (Sandbox Code Playgroud)

正如 @KarlKnetchel 所强调的,上面的代码具有与您最初的概念相同的漏洞。这不安全。如果您使用它,您绝对应该考虑在沙箱中运行它。