Raku Perl6:无法调用此对象(REPR:P6opaque;Parallel::ForkManager)

Raku Perl6:无法调用此对象(REPR:P6opaque;Parallel::ForkManager),raku,Raku,我试图在Perl6中使用Perl5的parallel::ForkManager 这几乎是对Perl5代码的精确翻译 CONTROL { when CX::Warn { note $_; exit 1; } } use fatal; role KeyRequired { method AT-KEY (\key) { die "Key {key} not found" unless self.EXISTS-KEY(key);

我试图在Perl6中使用Perl5的
parallel::ForkManager
这几乎是对Perl5代码的精确翻译

CONTROL {
    when CX::Warn {
        note $_;
        exit 1;
    }
}
use fatal;
role KeyRequired {
    method AT-KEY (\key) {
        die "Key {key} not found" unless self.EXISTS-KEY(key);
        nextsame;
    }
}

use Parallel::ForkManager:from<Perl5>;

sub run_parallel (@cmd) {
    my $manager = Parallel::ForkManager(8).new();
    for (@cmd) -> $command  {
        $manager.start and $manager.next;
        my $proc = shell $command, :out, :err;
        if $proc.exitcode != 0 {
            put "$command failed";
            put $proc.out.slurp;
            put $proc.err.slurp;
            die;
        }
        $manager.finish;
    }
    $manager.wait_all_children;#necessary after all lists
}

my @cmd;
my Str $dir = 'A/1';
for dir($dir, test => /\.vcf\.gz$/) -> $vcf {
    @cmd.append: "aws s3 cp $vcf s3://s3dir/$dir/"
}
put @cmd.elems;
run_parallel(@cmd);
控件{
当CX::Warn{
附注$;
出口1;
}
}
使用致命的;
需要角色密钥{
方法AT-KEY(\KEY){
除非self.EXISTS-Key(Key)存在,否则die“Key{Key}未找到”;
下一集;
}
}
使用Parallel::ForkManager:from;
并行子运行(@cmd){
my$manager=Parallel::ForkManager(8).new();
对于(@cmd)->$命令{
$manager.start和$manager.next;
my$proc=shell$command,:out,:err;
如果$proc.exitcode!=0{
放置“$命令失败”;
放入$proc.out.slurp;
放入$proc.err.slurp;
死亡
}
$manager.finish;
}
$manager.wait_all_children;#所有列表之后都需要
}
my@cmd;
我的Str$dir='A/1';
对于dir($dir,test=>/\.vcf\.gz$/)->$vcf{
@cmd.append:“aws s3 cp$vcf s3://s3dir/$dir/”
}
put@cmd.elems;
并行运行(@cmd);
基本上,我正在尝试并行化繁琐的shell命令

然而,这个神秘的错误出现了:

无法在中调用此对象(REPR:P6opaque;Parallel::ForkManager) 在块中2.aws_cp.p6线18处平行的子管道 2.aws_cp.p6第39行

为什么Perl6会这样说?怎么了?如何运行这些命令


也许有一种更为自然/惯用的方法可以在Perl6中并行运行shell命令?

您可能希望了解如何使用which在线程中异步运行外部命令,而无需分叉单独的代码实例来执行此操作

Perl5的Parallel::ForkManager可能无法在Perl6中工作,因为Inline::Perl5是如何实现的

Perl5将Perl5编译器/运行时嵌入到Perl6中

Parallel::ForkManager希望Perl5是自己运行的

如果您确实让它做了一些事情,而不是生成错误,那么它可能会破坏Perl6运行时。主要问题是使用
fork
。有关为什么
fork
是一个问题的更多信息,请参阅Bart Wiegmans(brrt)撰写的文章:


Perl6已经有一个类似的功能,更易于使用

sub-run_并行(@cmd){
my@children=do for(@cmd)->$command{
开始{
my$proc=shell$command,:out,:err;
如果$proc.exitcode!=0{
放置“$命令失败”;
放入$proc.out.slurp;
放入$proc.err.slurp;
死亡
}
}
}
等待孩子们;
}
start
是一个前缀,告诉运行时在不久的将来开始运行以下代码。它返回一个承诺。
wait
获取承诺列表并返回其结果列表

start
基本上调用
Promise.start
,类似于:

子开始(&code){
我的$promise=promise.new;
我的$vow=$promise.vow;
$*SCHEDULER.cue(
{$vow.keep(代码(| c))},
:捕获(->$ex{$vow.break($ex);}));
美元承诺
}
因此,它将使用
$*调度程序中的全局可用线程池。如果你想使用一个单独的,你可以

sub-run_并行(@cmd){
my$*SCHEDULER=ThreadPoolScheduler.new(最大线程数=>8);
my@children=do for(@cmd)->$command{
开始{
my$proc=shell$command,:out,:err;
如果$proc.exitcode!=0{
放置“$命令失败”;
放入$proc.out.slurp;
放入$proc.err.slurp;
死亡
}
}
}
等待孩子们;
}

不过,使用Proc::Async会更有意义。

我真的不建议尝试在Perl6中使用Perl5 forking代码,因为它有一个完全不同的管理器异步和并行代码系统。“forking”是这一尝试的正确术语,即并行运行shell命令@我明白了。我的观点是Perl6不使用Forking进行并行工作,而是使用线程。其他人指出了为什么他们认为P5的
parallel::ForkManager
似乎不太可能与P6一起工作。我对此一无所知。以下内容完全独立于此,而是以涉及线程的方式将P6与P5一起使用。根据,“如果您想安全地使用多个
内联::Perl5
interpeter,例如从Perl 6线程中,还可以添加
-Dusemultiplicity
选项”。甚至可以尝试一下该模块,它适用于有许多进程要并行运行的情况。