Python 子进程:为什么参数列表不能像完整的 shell 字符串一样工作?
预先感谢您的任何帮助。我对 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"
这样我就可以避免仅仅为了发送消息而写入文件。
我尝试使用子进程,无论是 call 还是 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”而不是管道,它也会失败。 “失败”通常是它会读为“<”和“file.with.body.info.txt”,就好像它们是进一步的收件人一样。换句话说,无论我是否说“shell = True”,子进程都无法将调用中的特殊字符解释为它们本身的特殊字符。 '<'不被识别为来自文件等的输入,除非我将所有内容都保存在一个大型调用中。
我理想中希望能够做的是这样的,因为它看起来更安全,也更灵活:
subprocess.call(['/bin/echo', varWithBody, '|', '/bin/mail', '-s', subjVariable, recipVariable,])
但子进程似乎根本不理解管道,我无法弄清楚如何将事物通过管道连接在一起当被困在蟒蛇后面时。
有什么建议吗?欢迎所有帮助,除了尝试解释如何使用“电子邮件”或“smtplib”模块。不管这个特定的应用程序如何,我真的很想学习如何更好地使用子进程,以便我可以将不同的程序结合在一起。我的理解是 python 在这方面应该相当不错。
谢谢!麦克风
Thanks in advance for any help. I am new to python, but not particularly new to scripting. I am trying to run a simple, automated email program, but the email module seems to be installed incorrectly on our system (I don't have 75% of the functions described in the python examples, only "message_from_string" and "message_from_file") and smtplib is overly complicated for what I need.
In fact, in simple bash terms, all I need is:
/bin/email -s "blah" "recipients" < file.with.body.info.txt
or,
echo "my body details" | /bin/email -s "blah" "recipients"
so that I can avoid having to write to a file just to send a message.
I tried using subprocess, either call or Popen, and the only way I could eventually get things to work is if I used:
subprocess.call('/bin/mail -s "blah" "recipients" < file.with.body.info.txt', shell=True)
A few things I specifically don't like about this method:
(1) I couldn't break things into a list or tuple, as it is supposed to work, so that I lost the whole advantage of subprocess, as I understand it, in keeping things secure. If I tried:
subprocess.call(['/bin/mail', '-s', subjVariable, recipVariable, '<', 'file.with.body.info.txt'], shell=True)
it would fail. Similarly, if I tried to use the pipe, '|', instead of reading from a file, it would fail. It was also failing if I used '-cmd' instead of a pipe. The "fail" was usually that it would read '<' and 'file.with.body.info.txt' as if they were further recipients. In other words, whether I said "shell = True" or not, subprocess was not able to interpret the special characters in the call as the special characters that they are. '<' wasn't recognized as an input from a file, etc., unless I kept everything in one large call.
What I would ideally like to be able to do, because it seems more secure, as well as more flexible, is something like this:
subprocess.call(['/bin/echo', varWithBody, '|', '/bin/mail', '-s', subjVariable, recipVariable,])
but it seems that pipes are not understood at all with subprocess and I cannot figure out how to pipe things together while stuck behind python.
Any suggestions? All help is welcome, except attempts to explain how to use the 'email' or 'smtplib' modules. Regardless of this particular application, I really want to learn how to use subprocess better, so that I can tie together disparate programs. My understanding is that python should be fairly decent at that.
Thanks! Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Python 文档似乎涵盖了这种情况。
我可能会做类似以下的事情
The Python docs seem to cover this situation.
What I'd probably do is something like the following
|
和<
不是参数;它们是 shell 重定向。要替换代码中的|
,请参阅这些说明。要替换
<
,请使用:例如。
subprocess.Popen(["cat"], stdin=open("file.txt", 'r'))
与cat
相同文件.txt
|
and<
are not arguments; they are shell redirections. To replace the|
in your code, see these instructions.To replace
<
, use:eg.
subprocess.Popen(["cat"], stdin=open("file.txt", 'r'))
is the same ascat < file.txt
<
、|
等是 shell 的功能,而不是操作系统的功能。因此,像子进程这样的东西不会知道它们的任何信息 - 在内部它只是将参数列表传递给等效的操作系统函数。使用子进程进行输入/输出重定向的方法是使用stdin
、stdout
和strerr
参数。您可以传入文件对象(尽管它必须包含文件描述符,但正常打开的文件总是包含文件描述符)或裸文件描述符。或者一个管道对象。该手册有一个替换管道的示例,只需替换带有文件对象的管道,您应该已准备就绪。
<
,|
etc are features of the shell, not the operating system. Therefore something like subprocess won't know anything about them - internally it's just passing the list of arguments to the equivalent OS functions. The way to do input/output redirection using subprocess is using thestdin
,stdout
andstrerr
parameters. You can pass in a file object (it has to contain a file descriptor, though, but normally opened files always do) or a naked file descriptor. Or a pipe object.The manual has an example for replacing a pipeline, just replace the pipe with a file object and you should be all set.
您需要使用
shell
参数通过 shell 运行命令:You need to run the command through the shell using the
shell
argument: