【问题标题】:Python subprocess: why won't the list of arguments work analogous to the full shell string?Python 子进程:为什么参数列表不像完整的 shell 字符串那样工作?
【发布时间】:2013-02-27 18:10:37
【问题描述】:

提前感谢您的帮助。我是 python 新手,但对脚本不是特别陌生。我正在尝试运行一个简单的自动化电子邮件程序,但我们的系统上似乎没有正确安装电子邮件模块(我没有 python 示例中描述的 75% 的函数,只有“message_from_string”和“message_from_file”)而 smtplib 对于我需要的东西来说过于复杂了。

事实上,用简单的 bash 术语来说,我所需要的只是:

/bin/email -s "blah" "recipients" < file.with.body.info.txt

或者,

echo "my body details" | /bin/email -s "blah" "recipients"

这样我就可以避免仅仅为了发送消息而写入文件。

我尝试使用子进程,无论是调用还是 Popen,我最终可以让事情正常工作的唯一方法是使用:

subprocess.call('/bin/mail -s "blah" "recipients" < file.with.body.info.txt', shell=True)

我特别不喜欢这种方法的几点:

(1) 我不能把事情分解成一个列表或元组,因为它应该起作用,所以我失去了子进程的全部优势,据我所知,在保证事情安全方面。如果我尝试过:

subprocess.call(['/bin/mail', '-s', subjVariable, recipVariable, '<', 'file.with.body.info.txt'], shell=True)

它会失败。同样,如果我尝试使用管道“|”而不是从文件中读取,它会失败。如果我使用“-cmd”而不是管道,它也会失败。 “失败”通常是它会读取“

我最希望能够做到的,因为它看起来更安全,也更灵活,是这样的:

subprocess.call(['/bin/echo', varWithBody, '|', '/bin/mail', '-s', subjVariable, recipVariable,])

但似乎子进程根本不理解管道,我无法弄清楚如何在被困在 python 后面时将它们连接在一起。

有什么建议吗?欢迎所有帮助,除了尝试解释如何使用“电子邮件”或“smtplib”模块。不管这个特定的应用程序是什么,我真的很想学习如何更好地使用子进程,这样我就可以将不同的程序联系在一起。我的理解是python在这方面应该是相当不错的。

谢谢!迈克

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    Python docs 似乎涵盖了这种情况。

    我可能会做如下的事情

    from subprocess import *
    readBody = Popen(["/bin/echo", varWithBody], stdout=PIPE)
    mail = Popen(["/bin/mail", "-s", subjVariable, recipVariable], stdin=readBody.stdout, stdout=PIPE)
    output = mail.communicate()[0]
    

    【讨论】:

    • 是的,这正是我想要的。谢谢!我想文档确实涵盖了它,但是其中一些内容的描述有点深奥,至少在您更好地理解该语言之前...
    【解决方案2】:

    |&lt; 不是参数;它们是外壳重定向。要替换代码中的|,请参阅these instructions

    要替换 &lt;,请使用:

     subprocess.Popen(["command", "args"], stdin=open("file.txt", 'r'))
    

    例如。

    subprocess.Popen(["cat"], stdin=open("file.txt", 'r'))cat &lt; file.txt 相同

    【讨论】:

      【解决方案3】:

      &lt;| 等是 shell 的特性,而不是操作系统的特性。因此,像 subprocess 这样的东西对它们一无所知 - 在内部它只是将参数列表传递给等效的 OS 函数。使用子进程进行输入/输出重定向的方法是使用stdinstdoutstrerr 参数。您可以传入一个文件对象(它必须包含一个文件描述符,但通常打开的文件总是如此)或一个裸文件描述符。或者一个管道对象。

      手册中有一个replacing a pipeline 的示例,只需将管道替换为文件对象即可。

      【讨论】:

        【解决方案4】:

        您需要使用shell 参数通过shell 运行命令:

        >>> import subprocess
        >>> subprocess.call('ls -a | cat', shell=True)
        .
        ..
        .git
        .gitignore
        doc
        generate_rands.py
        infile1
        infile2
        infile3
        matrix.pyc
        matrix.py~
        median.py
        problems
        simple_median.py
        test
        test_matrix.py
        test_matrix.py~
        test_median.py
        

        【讨论】:

          猜你喜欢
          • 2017-10-20
          • 2012-05-12
          • 2019-05-05
          • 1970-01-01
          • 2011-05-13
          • 1970-01-01
          • 1970-01-01
          • 2015-07-07
          • 1970-01-01
          相关资源
          最近更新 更多