Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:YAML函数字典:如何在不转换为字符串的情况下加载_Python_String_Python 3.x_Dictionary_Yaml - Fatal编程技术网

Python:YAML函数字典:如何在不转换为字符串的情况下加载

Python:YAML函数字典:如何在不转换为字符串的情况下加载,python,string,python-3.x,dictionary,yaml,Python,String,Python 3.x,Dictionary,Yaml,我有一个YAML配置文件,其中包含一个字典,如下所示: "COLUMN_NAME": column_function 它将字符串映射到函数(这些函数存在并且应该被调用) 但是,当我使用yaml加载它时,我看到加载的字典现在将字符串映射到字符串: 'COLUMN_NAME': 'column_function' 现在我无法按预期使用它-“column\u function”没有指向column\u function 加载我的dict以便它映射到我的函数,有什么好方法?在对这个问题进行了一些搜

我有一个YAML配置文件,其中包含一个字典,如下所示:

"COLUMN_NAME": column_function
它将字符串映射到函数(这些函数存在并且应该被调用)

但是,当我使用
yaml
加载它时,我看到加载的字典现在将字符串映射到字符串:

'COLUMN_NAME': 'column_function' 
现在我无法按预期使用它-
“column\u function”
没有指向
column\u function

加载我的
dict
以便它映射到我的函数,有什么好方法?在对这个问题进行了一些搜索和阅读之后,我对使用
eval
之类的东西非常谨慎,因为配置文件是由用户编辑的

我认为这与我的问题有关,但我不确定最好的方法是什么

  • 我认为,
    getattr
    setattr
    不适用,因为它们操作实例化对象,而我有一个简单的脚本
  • globals()
    vars()
    locals()
    为我提供了
    dict
    s变量,我想我应该使用
    globals()
    
我应该在配置
dict
中查找每个键值对的字符串吗?这是一个好方法:

for (key, val) in STRING_DICTIONARY.items():
    try: 
        STRING_DICTIONARY[key] = globals()[val]   
    except KeyError:
        print("The config file specifies a function \"" + val 
               + "\" for column \"" + key 
               + "\". No such function is defined, however. ")

要查找名称
val
并以通用方式对其进行评估,我将使用以下方法:

def fun_call_by_name(val):
    if '.' in val:
        module_name, fun_name = val.rsplit('.', 1)
        # you should restrict which modules may be loaded here
        assert module_name.startswith('my.')
    else:
        module_name = '__main__'
        fun_name = val
    try:
        __import__(module_name)
    except ImportError as exc:
        raise ConstructorError(
            "while constructing a Python object", mark,
            "cannot find module %r (%s)" % (utf8(module_name), exc), mark)
    module = sys.modules[module_name]
    fun = getattr(module, fun_name)
    return fun()
这是从
ruamel.yaml.constructor.py:find\u python\u name()
改编而来的,用于从字符串标量创建对象。如果提交的
val
包含一个点,它将假定您正在另一个模块中查找函数名

但我不会神奇地解释你顶级字典中的值。YAML有一个标记机制(对于特定的标记,
find\u python\u name()
方法开始起作用,以控制创建的实例的类型)。
如果您可以控制YAML文件的外观,请使用标记有选择地不创建字符串,如此文件
input.YAML

COLUMN_NAME: !fun column_function    # tagged
PI_VAL: !fun my.test.pi              # also tagged
ANSWER: forty-two                    # this one has no tag
假设一个子目录
my
,其中包含一个文件
test.py
,其中包含以下内容:

import math
def pi():
    return math.pi
您可以使用:

import sys
import ruamel.yaml

def column_function():
    return 3

def fun_constructor(loader, node):
    val = loader.construct_scalar(node)
    return fun_call_by_name(val)

# add the constructor for the tag !fun
ruamel.yaml.add_constructor('!fun', fun_constructor, Loader=ruamel.yaml.RoundTripLoader)

with open('input.yaml') as fp:
    data = ruamel.yaml.round_trip_load(fp)
assert data['COLUMN_NAME'] == 3
ruamel.yaml.round_trip_dump(data, sys.stdout)
要获得:

COLUMN_NAME: 3                       # tagged
PI_VAL: 3.141592653589793            # also tagged
ANSWER: forty-two                    # this one has no tag
如果您不关心将
数据
转储为保留注释的YAML,则可以分别使用
SafeLoader
safe_load()
而不是
RoundTripLoader
<代码>往返装载机()