我们正在将基础设施中的大量 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 中有更多最新的方法可以做到这一点,它们提供了几种处理远程进程中的缓冲/错误的方法 - 代价是大量的样板代码和复杂性。
但是 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 模块的文档。
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
它。
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:
...