带有 getattr 和 args/kwargs 的 Python 调用函数

如何解决带有 getattr 和 args/kwargs 的 Python 调用函数

我想从这样的字符串中调用带有 getattr(或者其他东西?)的模块函数:

import bar
funcStr = "myFunc(\"strParam\",123,bar.myenum.val1,kwarg1=\"someString\",kwarg2=456,kwarg3=bar.myenum.val2)"
[function,args,kwargs] = someParsingFunction(funcStr)
# call module function
getattr(bar,function)(*args,**kwargs)

如何从字符串中提取 argskwargs,以便将它们传递给 getattr? 我尝试了 literal_eval 方法与 pythons ast 模块。但是 ast 无法评估模块 bar 的枚举。 SO 上的所有其他示例都传递一个 kwargs 映射,其中仅包含字符串。他们尤其从不解析字符串中的参数。还是有其他方法可以直接从字符串中调用函数?

编辑: python 脚本从文件中读取函数字符串。因此不建议在此处使用 eval

EDIT2:使用 python 3.6.3

EDIT3:感谢前两个答案,我想出了两个想法。从输入字符串中解析出 argskwargs 后,有两种方法可以获得正确类型的参数。

  1. 我们可以使用 ast.literal_eval(<value of the argument>)。对于像 kwarg2 中的标准类型的参数,它将返回所需的值。如果这除外,这将发生在枚举中,那么我们将在 getattr 模块上使用 bar 并获取枚举。如果这也是例外,则字符串无效。
  2. 我们可以使用 inspect 模块并遍历 myFunc 的参数。然后对于每个 argkwarg,我们将检查该值是否是 myFunc 参数(类型)的实例。如果是这样,我们会将 arg/kwarg 转换为 myFunc 参数类型。否则我们会引发异常,因为给定的 arg/kwarg 不是 myFunc 参数的实例。这个解决方案比第一个更灵活。

这两种解决方案都更像是一种解决方法。第一次测试似乎有效。我稍后会在这里发布我的结果。

解决方法

这有帮助吗?

funcStr = r"""myFunc(\"strParam\",123,bar.myenum.val1,kwarg1=\"someString\",kwarg2=456,kwarg3=bar.myenum.val2)"""

def someParsingFunction(s):
    func,s1 = s.split('(',1)
    l = s1.replace('\\','').strip(')').split(',')
    arg_ = [x.strip('"') for x in l if '=' not in x]
    kwarg_ = {x.split('=')[0]:x.split('=')[-1] for x in l if '=' in x}
    return func,arg_,kwarg_

class bar:
    def myFunc(self,*args,**kwargs):
        print(*args)
        print(kwargs)

[function,args,kwargs] = someParsingFunction(funcStr)
getattr(bar,function)(*args,**kwargs)

# 123 bar.myenum.val1
# {'kwarg1': '"someString"','kwarg2': '456','kwarg3': 'bar.myenum.val2'}

替代

funcStr = r"""myFunc(\"strParam\",bar.val1,kwarg3=bar.val2)"""

def someParsingFunction(s):
    func,kwarg_

class Bar:
    def __init__(self):
        self.val1 = '111'

[function,kwargs] = someParsingFunction(funcStr)

bar = Bar()
obj_name = 'bar' + '.'
args = [bar.__getattribute__(x.split(obj_name)[-1]) if x.startswith(obj_name) else x for x in args]

print(args)
,
def get_bar_args(arg_str):
    """
        example:
        arg_str='bar.abc.def'
        assumess 'bar' module is imported
    """
    from functools import reduce
    reduce(getattr,arg_str.split('.')[1:],bar)

def parseFuncString(func_str):
    '''
        example: func_str = "myFunc(\"strParam\",kwarg3=bar.myenum.val2)"
    '''
    import re
    all_args_str = re.search("(.*)\((.*)\)",func_str)
    all_args = all_args_str.group(2).split(',')
    all_args = [x.strip() for x in all_args]
    kwargs = {kw.group(1): kw.group(2) for x in all_args if (kw:=re.search('(^\w+)=(.*)$',x))}
    pargs = [x for x in all_args if not re.search('(^\w+)=(.*)$',x)]
    pargs = [get_bar_args(x) if x.startswith('bar.') else x for x in pargs]
    kwargs = {k: get_bar_args(v) if v.startswith('bar.') else v for k,v in kwargs.items()}
    print(f'{all_args=}\n{kwargs=}\n{pargs=}')
    func_name = func_str.split("(")[0]
    return func_name,pargs,kwargs

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-