通过url route python导入文件

Luk*_*Kas 0 python url import flask

我试图在url路由的基础上导入Flask app上的文件.几天前我开始编写python,所以我不知道我做得好.我写这个:

@app.route('/<file>')
def call(file):
    __import__('controller.'+file)
    hello = Example('Hello world')
    return hello.msg
Run Code Online (Sandbox Code Playgroud)

我有其他文件调用example.py到控制器文件夹,其中包含:

class Example:
    def __init__(self, msg):
        self.msg = msg
Run Code Online (Sandbox Code Playgroud)

所以我从终端应用程序开始,我尝试进入localhost:5000/example.我试图在屏幕上显示,Hello world但给我下一个错误:

NameError: global name 'Example' is not defined
Run Code Online (Sandbox Code Playgroud)

谢谢大家!

Mar*_*ers 5

__import__返回新导入的模块; 该模块中的名称添加到您的全局变量中,因此您需要Example从返回的模块中将该类作为属性获取:

module = __import__('controller.'+file)
hello = module.Example('Hello world')
Run Code Online (Sandbox Code Playgroud)

__import__相当低级,您可能想要使用importlib.import_module():

import importlib

module = importlib.import_module('controller.'+file)
hello = module.Example('Hello world')
Run Code Online (Sandbox Code Playgroud)

如果您还需要动态获取类名,请使用getattr():

class_name = 'Example'
hello_class = getattr(module, class_name)
hello = hello_class('Hello world')
Run Code Online (Sandbox Code Playgroud)

Werkzeug包(由Flask使用)提供了一个有用的功能:动态werkzeug.utils.import_string()导入对象:

from werkzeug.utils import import_string

object_name = 'controller.{}:Example'.format(file)
hello_class = import_string(object_name)
Run Code Online (Sandbox Code Playgroud)

这封装了上述过程.

您需要非常小心地接受Web请求中的名称并将其用作模块名称.请对file参数进行消毒,只允许使用字母数字来防止使用相对导入.

您可以使用该werkzeug.utils.find_modules()函数来限制file此处的可能值:

from werkzeug.utils import find_modules, import_string

module_name = 'controller.{}'.format(file)
if module_name not in set(find_modules('controller')):
    abort(404)  # no such module in the controller package

hello_class = import_string(module_name + ':Example')
Run Code Online (Sandbox Code Playgroud)