如何像 Perl 一样在 Python 文件 open() 中链接命令行函数?

问题描述 投票:0回答:3

我们正在将基础设施中的大量 Perl 代码重写为 Python。语法相似,读起来也相似。然而,存在许多细微的差异,使得转换有点具有挑战性。

我们的 Linux 环境中有一个名为“read_file”的命令行实用程序。您将路径名传递给文件,read_file 将确定如何打开它并从中“读取”。您可以传入 *.txt、*.dat、*.gz、*.bz2、*.pgp 甚至 *.zip(只要 zip 存档中只有 1 个文件),read_file 将确定如何解压缩/解密并传递人类可读的输出流。

我们在 Perl 程序中充分利用了这一点,打开文件就像这样简单:

my $fh = IO::File->new();
$fh->open("read_file $file_name |") or abend_pgm("open: $!");
while ( my $line = <$fh> ) {
  ...
}

这会导致 Perl 下降到 shell,启动一个“read_file”,并将其输出作为 $fh->open() 的输入通过管道传输,这样 Perl 脚本只能看到解压缩/解密的文本,而没有任何特殊的文本。处理。

Python中有类似的方法可以实现这一点吗?

此外,是否可以通过写入完成类似的操作,以便将 Python open() 的输出直接通过“gzip”进行管道传输?在 Perl 中,它是这样完成的:

open (my $fh, "| /usr/bin/gzip -c > $file_name ");

这将打开一个文件进行输出,发送到 $fh 文件句柄的任何内容都将通过管道传输到 /usr/bin/gzip -c 并且压缩的输出将重定向到 $file_name。所有转换均由 Perl 和操作系统而不是脚本处理,这使得利用 Linux 本身提供的庞大函数库变得非常简单。

这是我必须执行 popen() 并从该输出中读取的内容吗?


我已经尝试过这个和它的变体,但不知道还能做什么:

>>> with open(" /ds/CENTOS/common/bin/read_file /ds/tmp/177598.TEST_20240225.dat.gz","r") as file1:
...   read_content = file1.read()
...   print(read_content)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: ' /ds/CENTOS/common/bin/read_file /ds/tmp/177598.NATL_340B_20240225.dat.gz'
>>>

在 Perl 中,我可以很好地访问该文件,它会解压缩并将文件打印到屏幕上:

perl -e 'my $fh = IO::File->new(); $fh->open("/ds/CENTOS/common/bin/read_file /ds/tmp/177598.TEST_20240225.dat.gz |"); while (my $line = <$fh>) { print $line; };'
python file
3个回答
1
投票

Python 中有更多最新的方法可以做到这一点,它们提供了几种处理远程进程中的缓冲/错误的方法 - 代价是大量的样板代码和复杂性。

但是 Python 仍然保留了无官僚主义的方式来做到这一点,那就是

os.popen
:

In [1]: import os

In [2]: print(os.popen("gunzip -c debuginfo.json.gz").read())
{
 "App": "com.whatsapp.w4b",
 "Architecture": "aarch64",
 "Board": "sm6150",
 "Build": "RP1A.200720.012.A705MNXXS5DWH1",
 "CCode": " ",
 "CPU ABI": "arm64-v8a",
(...)

如果您需要 2000 年代初引入的 Popen 的更多受控变体,请查看 subprocess 模块的文档。


1
投票

Python 标准库包含用于处理各种类型的压缩文件的工具,如数据压缩和归档中所述。它们通常可以像内置的

open
一样使用。以读取.gz文件为例,首先让我们创建这样的文件

echo "ABLE BAKER CHARLIE" > file.txt
gzip file.txt

然后我们可以用Python来做

import gzip
with gzip.open('file.txt.gz', 'rb') as f:
    file_content = f.read()
print(file_content)

提供输出

b'ABLE BAKER CHARLIE\n'

请记住,从标准库中确定使用 w.r.t 进行文件存储的哪个设备取决于您。请注意,您获得的字节为

file_content
如果您希望获取文本,则应该
.decode
它。


1
投票

Perl 的

open
函数可以实现很多类似于 Python 中
subprocess
模块的设计用途。 Python
open
用于打开文件,而不是执行任意 shell 管道。

例如,

my $fh = IO::File->new();
$fh->open("read_file $file_name |") or abend_pgm("open: $!");
while ( my $line = <$fh> ) {
  ...
}

成为

from subprocess import Popen, PIPE

p = Popen(["read_file", file_name], stdout=PIPE)
(stdout, _) = p.communicate()
for line in stdout:
    ...
© www.soinside.com 2019 - 2024. All rights reserved.