如何让 python 程序表现得像正确的 unix 工具?

ixt*_*lix 29 pipe python text-processing stdout stdin

我有一些 Python 脚本,我正在努力重写它们。我对他们都有同样的问题。

我不清楚如何编写程序以使它们表现得像适当的 unix 工具。

因为这

$ cat characters | progname
Run Code Online (Sandbox Code Playgroud)

和这个

$ progname characters
Run Code Online (Sandbox Code Playgroud)

应该产生相同的输出。

我能在 Python 中找到的最接近的东西是 fileinput 库。不幸的是,我真的不知道如何重写我的 Python 脚本,所有这些脚本都是这样的:

#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
    f = open(file)
    fs = f.read()
    regexnl = re.compile('[^\s\w.,?!:;-]')
    rstuff = regexnl.sub('', fs)
    f.close()
    print rstuff
Run Code Online (Sandbox Code Playgroud)

fileinput 库在有标准输入时处理标准输入,如果有文件则处理文件。但它迭代单行。

import fileinput
for line in fileinput.input():
    process(line)
Run Code Online (Sandbox Code Playgroud)

我真的不明白。我想如果您正在处理小文件,或者您对文件没有做太多事情,这似乎很明显。但是,就我而言,这比简单地打开整个文件并将其读入字符串要慢得多,如上所述。

目前我运行上面的脚本

$ pythonscript textfilename1 > textfilename2
Run Code Online (Sandbox Code Playgroud)

但我希望能够在管道中运行它(及其兄弟),比如

$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
Run Code Online (Sandbox Code Playgroud)

rah*_*hmu 15

检查文件名是否作为参数给出,否则从sys.stdin.

像这样的东西:

if sys.argv[1]:
   f = open(sys.argv[1])
else:
   f = sys.stdin 
Run Code Online (Sandbox Code Playgroud)

它类似于 Mikel 的答案,只是它使用了sys模块。我想如果他们把它放在那里,那一定是有原因的......

  • 哦绝对!我没有费心展示它,因为它已经在你的答案中展示了。在某些时候,您必须信任用户来决定她需要什么。但是,如果您认为这是最好的,请随时进行编辑。我的观点只是用 `sys.stdin` 替换 `"open(/dev/stdin")`。 (4认同)
  • 你可能想检查`if len(sys.argv)>1:` 而不是`if sys.argv[1]:` 否则你会得到一个索引超出范围的错误 (2认同)

Mik*_*kel 10

为什么不只是

files = sys.argv[1:]
if not files:
    files = ["/dev/stdin"]

for file in files:
    f = open(file)
    ...
Run Code Online (Sandbox Code Playgroud)

  • 应该使用`sys.stdin`,因为它比硬编码的文件路径更便携。 (13认同)

ixt*_*lix 5

事实证明,我更喜欢的做法是......(这是从一个名为Harbinger's Hollow的不错的 Linux 小博客中获取

#!/usr/bin/env python

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
    string = open(args.filename).read()
elif not sys.stdin.isatty():
    string = sys.stdin.read()
else:
    parser.print_help()
Run Code Online (Sandbox Code Playgroud)

我最喜欢这个的原因是,正如博主所说,如果在没有输入的情况下意外调用,它只会输出一条愚蠢的消息。它也很好地插入了我所有现有的 Python 脚本中,我已经修改了它们以包含它。

  • 有时您确实希望从 tty 交互式输入输入;检查 `isatty` 并退出不符合 Unix 过滤器的哲学。 (3认同)