【问题标题】:Forcing a python script to take input from STDIN强制 python 脚本从 STDIN 获取输入
【发布时间】:2013-03-21 19:48:48
【问题描述】:

我需要运行的 python 脚本仅从作为命令行参数传递的文件中获取输入,如下所示:

$ markdown.py input_file

有没有办法让它接受来自 STDIN 的输入?我希望能够通过 Bash 做到这一点,而无需显着修改 python 脚本:

$ echo "Some text here" | markdown.py

如果我必须修改 Python 脚本,我会怎么做?

(编辑:Here 是解析命令行选项的脚本。)

【问题讨论】:

    标签: python bash


    【解决方案1】:

    我不确定它的可移植性如何,但在 Unix-y 系统上,您可以将 /dev/stdin 命名为您的文件:

    $ echo -n hi there | wc /dev/stdin
           0       2       8 /dev/stdin
    

    【讨论】:

    • 谢谢!这正是我想要的。
    【解决方案2】:

    确保它位于文件顶部附近:

    import sys
    

    然后寻找这样的东西:

    filename = sys.argv[1]
    f = open(filename)
    

    并将其替换为:

    f = sys.stdin
    

    如果没有看到您开始使用的脚本,很难更具体。

    【讨论】:

    • Here 是文件。它使用 optparse 模块,因此没有 sys.argv[]。
    【解决方案3】:

    在代码中有这样一行:

    if not len(args) == 1:
    

    你可以做的是检查你是否没有文件名,而是使用“/dev/stdin”(在允许它的系统上)。

    另一种解决方案是替换:

    if not len(args) == 1:
        parser.print_help()
        return None, None
    else:
        input_file = args[0]
    

    if not len(args) == 1:
        input_file = sys.stdin
    else:
        input_file = open(args[0])
    

    这当然意味着返回的“input_file”不再是文件名而是文件对象,这意味着调用函数中的进一步修改。

    第一个解决方案是修改较少,但更具体的平台,第二个是更多的工作,但应该适用于更多的系统。

    【讨论】:

      【解决方案4】:

      我从您询问的有关 Python-Markdown 的问题的详细信息中猜测,因此我在源代码中为您查找了相关行:按照 Daniel 的方式进行操作,在 markdown/__init__.py 的第 443 行,你想替换

      input_file = codecs.open(input, mode="r", encoding=encoding)
      

      input_file = codecs.EncodedFile(sys.stdin, encoding)
      

      尽管之后您将无法实际处理文件,因此对于更普遍有用的 hack,您可以输入条件:

      if input:
          input_file = codecs.open(input, mode="r", encoding=encoding)
      else:
          input_file = codecs.EncodedFile(sys.stdin, encoding)
      

      然后你必须调整 markdown/commandline.py 以不退出,如果它没有给出文件名:更改第 72-73 行

      parser.print_help()
      return None, None
      

      input_file = None
      

      关键是,这并不是一件简单的事情。在这一点上,如果他没有打败我,我会建议使用像 Mark Rushakoff 那样的特殊文件;-)

      【讨论】:

        【解决方案5】:

        我建议去这里:

        http://codaset.com/repo/python-markdown/tickets/new

        并提交请求他们添加该功能的票证。这对他们来说应该是直截了当的,因此他们可能愿意继续这样做。

        【讨论】:

        • 那个网站看起来有点死,我认为去他们的Gitorious project,在一个分支中实施更改,并请求将其合并到项目中可能是一个更有成效的想法。
        【解决方案6】:

        在 bash 中,你也可以使用process substitution:

        markdown.py <(echo "Some text here")
        

        对于单个输入 /dev/stdin 有效,但进程替换也适用于多个输入(甚至输出)

        【讨论】:

          最近更新 更多