python - 使用 Python 对文件夹中的多个文件同时运行 perl 脚本

标签 python perl

这是我目前的 Perl 脚本:

#!/usr/bin/perl
use open qw/:std :utf8/;
use strict;
use warnings;

if (defined $ARGV[0]){
my $filename = $ARGV[0];
my %count;

open (my $fh, $filename) or die "Can't open '$filename' $!";
while (<$fh>)
{
        $count{ lc $1 }++ while /(\w+)/g;
}
close $fh;

my $array = 0;

foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count)
{
    print "$count{$word} $word\n" if $array++ < 10;
}

}else{
print "Please enter the name of the file: ";
my $filename = ($_ = <STDIN>);

my %count;

open (my $fh, $filename) or die "Can't open '$filename' $!";
while (<$fh>)
{
        $count{ lc $1 }++ while /(\w+)/g;
}
close $fh;

my $array = 0;

foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count)
{
    print "$count{$word} $word\n" if $array++ < 10;
}
}

这是我目前的 Python 脚本:

#!/usr/bin/env python3
import os

perlscript = "perl " + " perlscript.pl " + " /home/user/Desktop/data/*.txt " + " >> " + "/home/user/Desktop/results/output.txt"
os.system(perlscript)

问题:当数据文件夹中有多个 txt 文件时,脚本仅在一个文件上运行并忽略所有其他 txt 文件。有没有办法同时在所有 txt 文件上运行 perlscript?

另一个问题:我还尝试在执行后使用 os.remove 删除 txt 文件,但它们在 perlscript 有机会执行之前就被删除了。

有什么想法吗? :)

最佳答案

该 Perl 脚本处理一个文件。此外,通过 os.system 传递给 shell 的字符串不会按照 * shell glob 的预期扩展为带有文件列表的有效命令。

相反,请使用 os.listdirglob.globos.walk 在 Python 中构建文件列表。然后迭代该列表并在每个文件上调用该 Perl 脚本(如果它必须一次只处理一个文件)。或者,修改 Perl 脚本以处理多个文件,然后对整个列表运行一次。

保留当前 Perl 脚本并在每个文件上运行它

import os

data_path   = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"

for file in os.listdir(data_path):
    if not file.endswith(".txt"):
        continue

    print("Processing " + file)                      # better use subprocess
    run_perlscript = "perl " + " perlscript.pl " + \
        data_path + file  + " >> " + output_path + "output.txt"
    os.system(run_perlscript)

需要重写 Perl 脚本以删除不需要的重复代码。

但是,最好使用 subprocess运行和管理外部命令的模块。即使在 os.system 中也建议这样做。文档本身。 例如

import subprocess

with open(output_path + "output.txt", "a") as fout:
    for file in os.listdir(path):
        if not file.endswith(".txt"):
            continue 
        subprocess.run(["perl", "script.pl", data_path + file], stdout=fout)

在问题的 >> 重定向之后,文件以追加模式 ("a") 打开。

推荐subprocess.run自 python 3.5 起可用;否则使用 Popen .

另一个可以说是“正确”的选项是调整 Perl 脚本,以便它可以处理多个文件。然后您只需使用整个文件列表运行一次。

use strict;
use warnings;
use feature 'say';    
use open ':std', ':encoding(UTF-8)';

foreach my $filename (@ARGV) {
    say "Processing $filename";

    my %count;

    open my $fh, '<', $filename  or do {
       warn "Can't open '$filename': $!";
       next;
    };
    while (<$fh>) {   
        $count{ lc $1 }++ while /(\w+)/g;
    }   
    close $fh;

    my $prn_cnt = 0;
    foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count) {   
        print "$count{$word} $word\n" if $prn_cnt++ < 10; 
    }   
}

这会在无法打开的文件上打印一条警告,并跳到下一个文件。如果您希望脚本在任何意外文件上退出,请将 或 do { ... }; 替换为原始 die

然后,使用glob.glob现在举个例子

import subprocess

data_path   = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"

files = glob.glob(data_path + "*.txt")

with open(output_path + "output.txt", "a") as fout:
    subprocess.run(["perl", "script.pl", files], stdout=fout)

由于这会将整个列表作为命令参数传递,因此它假设没有(大量)数千个文件,从而超出管道或命令行的某些长度限制。

关于python - 使用 Python 对文件夹中的多个文件同时运行 perl 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56103985/

相关文章:

python - 使用字符串列表作为键更新嵌套 JSON 文件中的单个值

python - 将多种类型存储为 C++ 字典中的值?

web-services - 使用 wsdl 的 Perl Soap 服务

perl - 是否有与 Buildout 或 RVM 等效的 Perl?

perl - 后备打开文件 Perl

perl - 在许多java文件中将string1替换为string2,仅在注释中

python - 使用 Django Rest Framework 在 ModelViewSet 中使用自定义函数

python - 让seaborn条形图中的颜色与轴中的标签相匹配

javascript - 将 blob 保存到 python 中的文件

mysql - PERL:脚本未完成