【问题标题】:Standard input inconsistency between command line and subprocess.call命令行和 subprocess.call 之间的标准输入不一致
【发布时间】:2015-06-19 08:27:59
【问题描述】:

我想创建一个文件,用作 python 脚本的标准输入,并使用 subprocess.call 调用该脚本。

当我直接在命令行中执行它时,它工作正常:

输入文件:

# test_input
1/2/3

python 脚本

# script.py
thisDate = input('Please enter date: ').rstrip()

以下命令可以正常工作:

python script.py < test_input

但是当我尝试从另一个 python 脚本中执行以下操作时,它不起作用。 (来自this

outfile1 = open('test_input', 'w')
outfile1.write('1/2/3')
outfile1.close()

input1 = open('test_input')
subprocess.call(['python', 'script.py'], stdin=input1)

然后我收到以下错误:

>>>thisDate = input('Please enter date: ').rstrip()
>>>AttributeError: 'int' object has no attribute 'rstrip'

当我进行一些调试时,它似乎将整数 0 作为输入。

是什么导致了这里的不一致?这两种方法是否不等效(显然它们不是,但为什么)?我的最终目标是执行与上述命令行版本完全相同的任务。

谢谢

【问题讨论】:

  • 听起来像是 Python 2 与 Python 3 的问题。在 Python 2 中,input 将在返回结果之前将字符串计算为两个整数除法;您通常会改用raw_input。在 Python 3 中,input 的行为类似于(并替换)raw_input
  • 你是 100% 正确的。我将在编辑中反映我的解决方案。

标签: python subprocess stdin


【解决方案1】:

你在使用input的时候应该是raw_input,在python2中inputeval这个字符串。如果您使用python3 运行脚本,它将按原样运行,将python2 更改为raw_input

使用check_call 通常是更好的方法,使用with 打开文件。

import subprocess
with open('test_input') as input1:
    subprocess.check_call(['python3', 'script.py'], stdin=input1)

【讨论】:

  • 谢谢,是的,我确实想在 3 内完成。我应该在问题中指定。
  • @Malonge,我也推荐使用check_call。对于非零退出状态,它将引发 CalledProcessError。也可以使用with 打开您的文件。
【解决方案2】:

所以 chepner 是正确的。当我修改以下行时:

subprocess.call(['python', 'script.py'], stdin=input1)

到:

subprocess.call(['python3', 'script.py'], stdin=input1)

效果很好。

(我正在尝试在 python3 中执行此操作)

【讨论】:

    【解决方案3】:

    在第一种情况下,文件有两行,input() 读取并解析第一行,即注释。

    在第二种情况下,注释行丢失,因此 Python 读取并解析一个数字。

    您可能打算使用raw_input(),或使用 Python 3 运行脚本。

    (您可能还希望输入文件以换行符结尾,当您已经在运行 Python 时,使用 subprocess.call() 运行 Python 并没有真正意义。)

    【讨论】:

      【解决方案4】:

      python script.py &lt; test_input 命令应该失败。您可能的意思是:python3 script.py &lt; test_input 而不是由于其他答案中提到的 Python 2 上的 input()raw_input() 之间的差异。 python as a rule 指的是 Python 2 版本。

      如果 parent 脚本仅使用 python3 运行,那么您可以使用 sys.executable 使用相同的 python 版本(相同的可执行文件)运行子脚本:

      #!/usr/bin/env python3
      import subprocess
      import sys
      
      with open('test_input', 'rb', 0) as input_file:
          subprocess.check_call([sys.executable or 'python3', 'script.py'],
                                stdin=input_file)
      

      如果父母和孩子可能使用不同的python版本,则在script.py中设置正确的shebang,例如#!/usr/bin/env python3并直接运行脚本:

      #!/usr/bin/env python
      import subprocess
      
      with open('test_input', 'rb', 0) as input_file:
          subprocess.check_call(['./script.py'], stdin=input_file)
      

      这里,子脚本可以选择自己的python版本。确保脚本具有可执行权限:chmod +x script.py。注意:适用于 Windows 的 Python Launcher 也可以理解 shebang 语法。

      不相关:使用.communicate() 而不是outfile1.write('1/2/3')

      #!/usr/bin/env python3
      from subprocess import Popen, PIPE
      
      with Popen(['./script.py'], stdin=PIPE, universal_newlines=True) as p:
          p.communicate('1/2/3')
      

      【讨论】:

        猜你喜欢
        • 2011-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 2021-04-29
        • 2012-05-10
        相关资源
        最近更新 更多