2014-11-25 3 views
0

Im пытается импортировать файлы на приложение Flask в базе URL-адреса. Я начал кодировать python несколько дней назад, поэтому у меня нет идеи, если я буду делать это хорошо. Я пишу это:файл импорта по URL-адресу маршрута python

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

И у меня есть другой файл с именем example.py в папку контроллера, который содержит это:

class Example: 
    def __init__(self, msg): 
     self.msg = msg 

Так я начать с терминала приложение и я пытаюсь войти в localhost:5000/example. Im пытается показать в экране Hello world но дайте мне следующую ошибку:

NameError: global name 'Example' is not defined 

Спасибо за все!

+1

Есть ли у вас конкретная причина использовать '__import __ ()' instea d 'import module'? –

ответ

5

__import__ возвращает вновь импортированный модуль; имена из этого модуля являются не добавлены в глобал, так что вам нужно, чтобы получить Example класс в качестве атрибута из возвращаемого модуля:

module = __import__('controller.'+file) 
hello = module.Example('Hello world') 

__import__ довольно низкий уровень, вы, вероятно, хотите использовать importlib.import_module() вместо :

import importlib 

module = importlib.import_module('controller.'+file) 
hello = module.Example('Hello world') 

Если вам нужно динамически получить имя класса тоже использовать getattr():

class_name = 'Example' 
hello_class = getattr(module, class_name) 
hello = hello_class('Hello world') 

Werkzeug пакет (используется колба) предлагает полезные функции здесь: werkzeug.utils.import_string() импортирует объект динамически:

from werkzeug.utils import import_string 

object_name = 'controller.{}:Example'.format(file) 
hello_class = import_string(object_name) 

Это инкапсулирует выше процесс.

Вы должны быть чрезвычайно осторожным с принятием имен из веб-запросов и использованием этих имен модулей. Проведите дезинфекцию аргумента file и позвольте буквенно-цифровым методам предотвращать использование относительного импорта.

Вы можете использовать werkzeug.utils.find_modules() function, чтобы ограничить возможные значения 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') 
+0

Huh, не знаю о importlib - я только что узнал что-то новое :) –

+0

Это именно то, что я хочу. Благодаря! –

+1

Я должен согласиться с @Martijn Pieters здесь - это звучит как-то рискованно делать в веб-приложении. Вы уверены, что это необходимо в вашем случае? –

0

Я думаю, вы могли бы не добавить каталог в файл, добавьте следующий код в предыдущей программе питона

# Add another directory 
import sys 
sys.path.insert(0, '/your_directory') 

from Example import Example 
+0

Да, но я пытаюсь сделать это динамически, не знаю, имя класса или файла –

+0

попробуйте импортировать os и получить все подкаталоги 'os.listdir ('./ ') ', сделать итерацию для импорта всех подкаталогов – ChesterL

0

Есть два способа для вас, чтобы сделать импорт в Python:

import example 

e = example.Example('hello world') 

или

from example import Example 

e = Example('hello world') 
+0

Уверен, но ОП пытается использовать * динамический * импорт. –

+0

Возможно, но он этого не писал, и он также заявил, что он только начал с python пару дней назад. Я предпочитаю сначала основываться на –

+0

Из [комментария другого ответа] (http://stackoverflow.com/questions/27136729/import-file-by-url-route-python/27136850?noredirect=1#comment42771893_27136820): * да, но я пытаюсь сделать это динамически, не знаю имя класса или файла * –

Смежные вопросы