Скажем, у меня есть файл JSON как таковой:

{
  "x":5,
  "y":4,
  "func" : def multiplier(a,b):
               return a*d
}

Это слишком упрощает то, что я хочу попробовать, но в основном я пытаюсь
записать UDF Python в файл JSON. Есть ли способ сделать это так, чтобы когда я делать:

with open('config.json') as f:
    data = json.load(f)

Я могу получить доступ к этим значениям и сделать что-то вроде:

v1, v2 = data['x'], data['y']
mult = data['func']
print(mult(v1,v2))

Чтобы получить ожидаемый результат: 20

ПРИМЕЧАНИЕ . Насколько я понимаю, JSON не хранит функции, поэтому, возможно, я смогу сохранить его в виде строки, а затем в моем скрипте python проанализировать строку в функции? Не слишком уверен.

3
Connor Watson 20 Авг 2018 в 21:45

4 ответа

Лучший ответ

Если вам действительно необходимо сохранить функцию во внешнем json-файле, одним из способов будет сохранение лямбда-функции и использование функции eval для вызова ее из вашего скрипта. Но я не очень рекомендую это для хорошей практики ...

< Сильный > config.json

{
  "x": 5,
  "y": 4,
  "func": "lambda a, b : a * b"
}

Ваш файл Python

import json


def main():

    with open('config.json') as f:
        data = json.load(f)

    v1, v2 = data['x'], data['y']
    multiplier = eval(data['func'])
    print(multiplier(v1, v2))


if __name__ == "__main__":
    main()

< Сильного > Demo

Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin

In[2]: ls
a.py
config.json

In[3]: import json

In[4]: def main():
  ...: 
  ...:     with open('config.json') as f:
  ...:         data = json.load(f)
  ...: 
  ...:     v1, v2 = data['x'], data['y']
  ...: 
  ...:     multiplier = eval(data['func'])
  ...: 
  ...:     print(multiplier(v1, v2))
  ...:    

In[5]: main()
20
2
smallwat3r 20 Авг 2018 в 20:48

Что-то, что стоит попробовать, это просто сохранить его как строку.

Вы можете делать такие вещи, как

my_func = "
def function(a,b):
   constant = {input_var}
   return a*b + constant
"
my_func.format(input_var = 5)

exec(my_func)
function(1,2) # will return 7

Это создаст объект функции, которую вы можете вызвать. Не совсем уверен, что вы пытаетесь сделать, но создание файла json, как показано ниже, должно дать вам то, что вы хотите сделать: (Я добавил оболочку 'func', потому что я предполагаю, что у вас будет несколько функций в одном JSON)

function_json = {
'func': {
    'x':5
    'y':4
    'multiplier':
'def multiplier(a,b):
    return a*b'
}

x=function_json['func']['x']
y=function_json['func']['y']
exec(function_json['func']['multiplier'])
multiplier(x,y) # will return 20

Надеюсь это поможет

2
Ethan Kulla 20 Авг 2018 в 20:59

Python имеет встроенное имя модуля marshal, которое может справиться с этим.

import marshal, ujson as json

def multiplier(a, b):
    return a * b

x = {
  "x":5,
  "y":4,
  "func" : marshal.dumps(multiplier.func_code)
}

x = json.dumps(x)
print(x)

И вернуть его обратно ...

x = json.loads(x)
x = marshal.loads(x['func'])
# maybe save the function name in dict
func = types.FunctionType(x, globals(), "some_func_name") 

print(func(2,4))
5
eatmeimadanish 20 Авг 2018 в 21:03

Я опробовал и объединил решения с ethan-kulla и eatmeimadanish

Следующий код работает:

my_func = '''
def function(a,b):
   constant = {input_var}
   return a*b + constant
'''

exec(my_func.format(input_var=5), globals())
# For Python 3.x, use globals() to change global context
function(2,2)
1
yoonghm 8 Июн 2019 в 12:02
51936785