将文件x中指定的函数作为命令行参数传递给python中的文件y的最佳方法

Posted

技术标签:

【中文标题】将文件x中指定的函数作为命令行参数传递给python中的文件y的最佳方法【英文标题】:Best way to pass function specified in file x as commandline parameter to file y in python 【发布时间】:2020-02-21 18:48:16 【问题描述】:

我正在编写一个包装器或管道来创建一个 tfrecords 数据集,我想向该数据集提供一个函数以应用于该数据集。

我想让用户能够注入在另一个 python 文件中定义的函数,该文件在我的脚本中调用以转换数据。

为什么?用户唯一需要做的就是编写将他的数据转换为正确格式的函数,然后由现有代码完成剩下的工作。

我知道我可以让用户在同一个文件中编写函数并调用它,或者有一个导入语句等。

作为一个最小的例子,我想要文件 y.py

def main(argv):
    # Parse args etc, let's assume it is there.

    dataset = tf.data.TFRecordDataset(args.filename)
    dataset = dataset.map(args.function)
    # Continue with doing stuff that is independent from actual content

所以我想做的是这样的

    python y.py --func x.py my_func

并在dataset.map(...)中使用x.py my_func中定义的函数

有没有办法在 python 中做到这一点,如果有,这是最好的方法吗?

【问题讨论】:

那么你在 x.py 中定义了一个函数 my_func 吗?为什么不 from x import my_func 然后调用 my_func(...) 就像您通常使用本地定义的函数一样?或者import x 然后打电话给x.my_func(...) @JustinEzequiel 正如问题中提到的,我知道这个解决方案,但我不想使用它,但能够将函数传递给调用脚本。 那你见过importlib.import_module吗?这是你的用例,我不明白。 “我正在编写一个包装器或管道来创建一个 tfrecords 数据集,我想向该数据集提供一个应用于数据集的函数。”这是我的用例。 “有没有办法在 python 中做到这一点,如果是的话,这是最好的方法吗?”这就是问题。所以你的答案是,没有办法做到这一点,或者说没有任何情况下这是有意义的? 【参考方案1】:
    将文件名作为参数传递给脚本(和函数名) 将文件读入字符串,可能提取给定函数 使用 Python exec() 执行代码

一个例子:

file = "def fun(*args): \n  return args"
func = "fun(1,2,3)"

def execute(func, file):
    program = file + "\nresult = " + func
    local = 
    exec(program, local)
    return local['result']

r = execute(func, file)
print(r) 

类似于here,但是我们必须使用locals(),因为我们不在全局范围内调用exec

注意:exec 的使用有些危险,您应该确保该功能是安全的 - 如果您正在使用它就可以了!

希望这会有所帮助。

【讨论】:

既然exec返回None,它怎么能作为一个函数来返回转换后的元素呢?或者它如何返回指定函数返回的任何内容? 讨论here。肯定有比使用exec 更好的方法! 好的,我可以通过使用另一个包装函数使其工作,这将是一个完全解决问题中指定问题的解决方案。因此,我正在等待更多反馈,但如果没有更好的反馈,如果您稍微编辑它以包含此信息,这可能是一个可接受的答案;) @hechth 我已经更新了一个例子。我希望这就是你所追求的。【参考方案2】:

好的,我现在使用来自 cmets 和 this answer 的信息自己编写了答案。

    import importlib, inspect, sys, os
    # path is given path to file, funcion_name is name of function and args are the function arguments

    # Create package and module name from path
    package = os.path.dirname(path).replace(os.path.sep,'.')
    module_name = os.path.basename(path).split('.')[0]

    # Import module and get members
    module = importlib.import_module(module_name, package)
    members = inspect.getmembers(module)

    # Find matching function
    function = [t[1] for t in members if t[0] == function_name][0]
    function(args)

这正好解决了这个问题,因为我得到了一个可调用的函数对象,我可以调用、传递、将其用作普通函数。

【讨论】:

以上是关于将文件x中指定的函数作为命令行参数传递给python中的文件y的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

将命令行参数传递给函数

将数组作为命令行参数传递给 Asp.Net Core

将命令行参数传递给调用带有装饰器参数的装饰函数的函数

如何将命令行参数传递给 c 程序

将可变数量的 bash 命令行参数传递给 MATLAB 函数

Vue.js 将函数传递给道具不起作用