使用Python子进程命令调用C编译器

sqougxex  于 2023-03-07  发布在  Python
关注(0)|答案(3)|浏览(123)

我试图用Python编译一个C程序,想给予“〈”操作符输入,但它没有按预期工作。如果我编译C程序,并通过文件输入来运行它,它就能工作;例如

./a.out <inp.txt works

但同样,如果我尝试使用Python脚本执行此操作,结果并不完全符合预期。

import subprocess
subprocess.call(["gcc","a.c","-o","x"])
subprocess.call(["./x"])

以及

import subprocess
subprocess.call(["gcc","a.c","-o","x"])
subprocess.call(["./x","<inp.txt"])

两个脚本都要求通过终端输入。但是我认为在第二个脚本中它应该从文件中读取。为什么两个程序的工作方式是一样的?

ruarlubt

ruarlubt1#

作为对乔纳森·莱弗勒和阿拉斯泰尔有益回答的补充:
假设 you 控制着要传递给shell执行的字符串,我认为使用shell来方便没有什么错。[1]

subprocess.call()有一个可选的布尔shell参数,该参数会将命令传递给 shell,从而启用I/O重定向、引用环境变量......:

subprocess.call("./x <inp.txt", shell = True)

注意整个命令行是如何作为 * 单个 * 字符串而不是参数数组传递的。
[1]避免在以下情况下使用shell:

  • 如果你的Python代码必须运行在非Unix平台上,比如Windows
  • 如果性能是最重要的。
  • 如果您发现自己将任务“外包”到Python端会更好地处理。
    如果您担心shell环境缺乏可预测性(如@alastair):
  • subprocess.callshell = True***总是 * 创建/bin/sh**的非交互式非登录示例-请注意,使用的不是 * 用户的 * 默认shell。
  • sh不读取非交互式非登录shell(既不是系统范围的也不是用户特定的shell)的初始化文件
  • 请注意,即使在sh伪装成bash的平台上,bash在作为sh调用时也会这样做。
  • 使用shell = True创建的每个shell示例都是自己的世界,其环境既不受以前的shell示例的影响,也不影响以后的shell示例。
  • 但是,创建的shell示例 * 确实 * 继承了 * python进程本身的 * 环境
  • 如果Python程序是从交互式shell启动的,那么shell的环境是继承的,注意这只与当前工作目录和环境变量有关,而与别名、shell函数和shell变量无关。
    一般来说,这是一个 * 特性,因为Python(CPython)本身被设计成可以通过环境变量来控制(对于Python 2.x,请参见https://docs.python.org/2/using/cmdline.html#environment-variables;对于3.x版本,请参见)。
    如果需要,您可以通过env参数向shell * 提供您自己的环境;但是请注意,您必须在该事件中提供 * 整个 * 环境,如果需要,可能包括USERHOME等变量;简单示例,明确定义$PATH
subprocess.call('echo $PATH', shell = True, \
                env = { 'PATH': '/sbin:/bin:/usr/bin' })
bqjvbblv

bqjvbblv2#

shell为一个进程做I/O重定向。根据你所说的,subprocess模块不做这样的I/O重定向。为了演示,运行:

subprocess.call(["sh","-c", "./x <inp.txt"])

这将运行shell,并应重定向I/O。在您的代码中,您的程序./x被给定了一个参数<inp.txt,它将忽略该参数。
注意:对subprocess.call的替代调用纯粹是出于诊断目的,而不是推荐的解决方案,推荐的解决方案包括阅读(Python 2)subprocess模块文档(或Python 3模块文档),以了解如何使用该模块进行重定向。

import subprocess
i_file = open("inp.txt")
subprocess.call("./x", stdin=i_file)
i_file.close()

如果您的脚本即将退出,这样您就不必担心浪费文件描述符,您可以将其压缩为:

import subprocess
subprocess.call("./x", stdin=open("inp.txt"))
vhipe2zx

vhipe2zx3#

默认情况下,subprocess模块不向shell传递参数,为什么呢?因为通过shell运行命令是 * 危险的 *;除非它们被正确地引用和转义(这很复杂),否则通常有可能使执行此类操作的程序运行不需要的和意外的shell命令。
无论如何使用shell都是错误的,如果你想从一个特定的文件中获取输入,你可以使用subprocess.Popen,将stdin参数设置为inp.txt文件的文件描述符(你可以通过调用fileno()这个Python文件对象来获得文件描述符)。

相关问题