Inline::Python
0.56,尝试从 Perl 调用带有命名参数的 Python 函数。我已根据要求用可以运行的示例替换了原始代码片段:
use strict;
use warnings;
use 5.16.3;
use Inline Python => <<'END_OF_PYTHON_CODE';
# Interface
def get_sbom_of_package (
package_name = None,
target_path = None,
):
assert package_name is not None
assert target_path is not None
print ( package_name, target_path )
return package_name
END_OF_PYTHON_CODE
my $package = 'thePackage';
my $target_path = $ENV{HOME};
my $sbp = get_sbom_of_package(
package_name => $package ,
target_path => $target_path
);
say $sbp;
我的错误是:
TypeError: get_sbom_of_package() takes from 0 to 2 positional arguments but 8 were given at (eval 3) line 3.
我还需要做内联 Python 来了解我正在为其提供命名参数吗?我已将 Perl 中的调用替换为
my $sbp = get_sbom_of_package(
$package ,
$target_path
);
而且效果很好。我想要么是
从最有可能到最不可能排序。 :-)
如果我正确读取 XS 并记住我的 Python 扩展模块工作,则这不是直接可能的。
Inline::Python
似乎使用 PyObject_CallObject
调用 py 可调用对象,它传递参数元组 - 没有任何命名/关键字参数。
因此,您必须自己完成此操作,也许可以通过在 py 可调用对象周围放置一个包装器,该包装器理解您所说的
parameter => value, ...
的含义并构造要传递的正确元组。当然,您还需要多余地了解默认值。您可能会 rev Inline::Python
以支持询问可调用函数的签名以查找关键字参数...但是您仍然需要调整这些语义以适应普通 Perl 子例程自己调用。
Note 这是为了勾画这样的想法:“命名参数”在 Perl 中实现为散列(ref)——> 在 Python 中实现字典,然后在 Python 端使用命名参数执行任何需要完成的操作手。无论如何,将其他需要的参数添加到列表(或字典)中,例如函数名称、数组引用或诸如此类的东西。
最终目的没有解释,但如果澄清的话我可以添加更具体的代码。 (脚注中给出了如何使用它的猜测,以及另一种相当通用的方式。‡)
尝试的代码将四 (4) 个参数传递给 Perl 的函数调用,† 而 Python 的函数被编写为采用两个参数(每个参数都有一个默认值)。
如果要将命名参数传递给 Python 函数,一种方法是传递字典。那么这也顺便模仿了你的 Perl 使用
def adict(d):
for key in d:
print("key:", key, "value:", d[key])
通过这种方式,可以将 Perl 中的调用者(哈希)中的命名参数映射到 Python(字典),将其留给在此包装器中构建的普通 python->python 调用。
那么你的代码可以是
use warnings;
use strict;
use feature 'say';
use Inline::Python;
my $package = 'thePackage';
my $target_path = $ENV{HOME};
call_py( { # note -- pass a hashref
package_name => $package, target_path => $target_path
} );
use Inline Python => <<'END_PY'
def call_py(d):
for key in d:
print(key + " => " + d[key])
# ...
# prepare and make other (python-to-python) calls as needed
END_PY
如果需要从 Python 函数进行特定的进一步调用(通过命名参数?),请展示它们的外观,我可以添加到这个简单的示例中。
请参阅下文‡,了解我对这个问题的意图的猜测。
此打印(我的路径经过编辑)
目标路径 => /... package_name => 包
或者可以设计一个系统来传递 Perl 的四个参数并在 Python 中获取它们并将它们解释为名称 => 值对,但为什么呢?
一旦 Python 函数中的参数从字典中解压出来,以及可能添加到参数列表中的任何其他内容以及通过 hash(ref) 从 Perl 发送的命名参数的字典,就可以进一步生成 python -> python有需要请致电。
† Perl 中的函数采用标量列表。时期。所以这个
func(package_name => $package, target_path => $target_path)
甚至这个
my %ph = (package_name => $package, target_path => $target_path);
func( %ph );
真的是这个吗
func('package_name', $package, 'target_path', $target_path)
“fat comma”(
=>
)是一个逗号,因此它的左侧参数也被引用。
‡ 想象一下,这样做的目的是能够从 Perl 中调用 Python 中的一个很棒的
py_lib
,以某种方式通过“命名参数”(请澄清)。以下是一些猜测
use warnings;
use strict;
use feature 'say';
use Inline::Python;
my $package = 'thePackage';
my $target_path = $ENV{HOME};
call_py({ package_name => $package, target_path => $target_path });
use Inline Python => <<'END_PY'
def call_py(d):
print(d)
# prepare and make other (python-to-python) calls as needed
print("\nArgs with these names passed from Perl:")
py_lib_kw( pack=d['package_name'], path=d['target_path'] )
print("\nVariable number of named args passed from Perl:")
py_lib_kwargs( **d )
def py_lib_kw(path=None, pack=None):
print ("package is " + pack + " and path is " + path)
def py_lib_kwargs(**data):
for val in data:
print(val + " => " + data[val])
END_PY