it-swarm.com.ru

загрузить python код во время выполнения

Я хотел бы загрузить файл .py во время выполнения. Этот файл .py в основном является файлом конфигурации в следующем формате:

var1=value  
var2=value  
predicate_function=func line : <return true or false>  

После загрузки этого файла я хотел бы получить доступ к var1, var2 и predicate_function. Для каждой строки я передам ее функции предиката, и если она вернет false, я ее проигнорирую.

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

Пояснение: может быть любое количество этих конфигурационных файлов, которые мне нужно передать основной программе, и я не буду знать их имена до времени выполнения. Google говорит мне, что я должен использовать __import__. Я не уверен, как правильно использовать этот метод, а затем получить доступ к переменным импортированного файла.

16
Shahbaz

Вам просто нужно иметь возможность динамически определять импорт, а затем динамически получать переменные.

Допустим, ваш конфигурационный файл bar.py и выглядит так:

x = 3
y = 4
def f(x): return (x<4)

Тогда ваш код должен выглядеть так:

import sys

# somehow modnames should be a list of strings that are the names of config files
#
# you can do this more dynamically depending on what you're doing                                                                                                     
modnames = ['bar']

for modname in modnames:
  exec('import %s' % modname)

for modname in modnames:
  mod = sys.modules[modname]
  for k in mod.__dict__:
    if k[:2] != '__':
      print modname, k, mod.__dict__[k]

Я получаю этот вывод:

bar f <function f at 0x7f2354eb4cf8>
bar x 3
bar y 4

Тогда у вас как минимум есть все переменные и функции. Я не совсем получил то, что вы хотели от функций предикатов, но, возможно, вы можете получить это самостоятельно.

10
forefinger

Как написано в официальная документация python , если вы просто хотите импортировать модуль по имени, вы можете найти его в словаре sys.modules после использования __import__.

Предположим, что ваша конфигурация находится в myproject.mymodule, вам нужно сделать так:

module_name = 'myproject.mymodule'

import sys
__import__(module_name)
mymodule = sys.modules[module_name]

# Then you can just access your variables and functions
print mymodule.var1
print mymodule.var2
# etc...

Вы также можете использовать возвращаемое значение оператора __import__, но вам необходимо полностью понять как python работает с пространствами имен и областями видимости .

14
Clément

Если импортированный модуль находится на обычном пути поиска, вы можете использовать __import__ .

Если вам нужно загрузить модуль по произвольному пути в файловой системе, используйте imp.load_module .

Обязательно учтите последствия для безопасности загрузки произвольного пользовательского кода.

7
oefe

Чтобы получить доступ к другому модулю Python, вы импортируете его. execfile была упомянута парой людей, но это грязно и опасно. execfile загромождает ваше пространство имен, возможно, даже портит код, который вы запускаете. Если вы хотите получить доступ к другому исходному файлу Python, используйте оператор import.

Еще лучше было бы вообще не использовать файл Python для конфигурации, а использовать встроенный модуль ConfigParser или формат сериализации, такой как JSON. Таким образом, ваши файлы конфигурации не позволяют выполнять произвольный (возможно, вредоносный) код, не требуют, чтобы люди знали Python, чтобы сконфигурировать вашу программу, и могут быть легко изменены программно.

7
Mike Graham

В Python 2.*, execfile работает (я рекомендую передать определенный словарь и получить доступ к переменным оттуда - как говорится в примечании в документации, execfile не может влиять на вызывающую функцию locals() словарь).

В Python 3.* execfile был удален, так что вместо этого:

with open('thefile.py') as f:
  exec(f.read(), somedict)
2
Alex Martelli

Я опаздываю на вечеринку, но, тем не менее, хочу представить альтернативный ответ.

Если вы хотите импортировать код, не влияя на глобальное пространство имен модуля, вы можете создать анонимный модуль (используя types.ModuleType) и загрузить в него произвольный код (используя compile и exec). Например, вот так:

import types

filename = "/path/to/your/file.py"
with open(filename) as fp:
    code = compile(fp.read(), filename, "exec")
config_module = types.ModuleType("<config>")
exec code in config_module.__dict__

Затем вы можете получить доступ к переменным как config_module.var1, & c.

2
Dolda2000

Если вы хотите иметь файл конфигурации, который будет редактироваться пользователем, только когда программа не запущена, просто импортируйте его как обычный python файл

то есть.

main.py:

import config
print config.var1

config.py:

var="var12"
var2 = 100.5
1
Simon Callan

попробуйте модуль imp: http://docs.python.org/library/imp.html

0
dzen

Поскольку версия Python четко не упомянута, стоит отметить, что модуль imp устарел в более новых Python версии в пользу модуля importlib . пример здесь.

0
Tom