簡體   English   中英

使用Python子進程命令調用C編譯器

[英]Invoking C compiler using Python subprocess command

我正在嘗試使用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"])

兩個腳本都要求終端輸入。 但我認為在第二個腳本中它應該從文件中讀取。 為什么兩個程序都一樣?

補充@Jonathan Leffler@ alastair 有用答案:

假設控制了傳遞給shell執行的字符串,我認為使用shell是為了方便。 [1]

subprocess.call()有一個可選的Boolean shell參數,它會將命令傳遞給shell ,啟用I / O重定向,引用環境變量,......:

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

請注意整個命令行如何作為單個字符串而不是參數數組傳遞


[1] 在下列情況下避免使用shell:

  • 如果你的Python代碼必須在比Unix類的,如Windows 平台上運行
  • 如果表現至關重要。
  • 如果你發現自己在Python方面更好地處理“外包”任務。

如果您擔心shell環境缺乏可預測性 (如@alastair所示):

  • subprocess.callshell = True 總是創建的非交互式非登錄實例/bin/sh -請注意,這不是所使用的用戶的默認外殼。
  • sh 不讀取非交互式非登錄shell的初始化文件 (既不是系統范圍的也不是用戶特定的)。
    • 請注意,即使在平台上,其中shbash偽裝, bash時的調用將這樣的行為sh
  • 使用帶有shell = True subprocess.call創建的每個shell實例都是它自己的世界,它的環境既不受以前的shell實例的影響,也不影響以后的實例。
  • 但是, 創建shell實例確實繼承了python進程本身環境
    • 如果從交互式shell啟動Python程序,則繼承該shell的環境。 請注意,這僅適用於當前工作目錄環境變量 ,而不適用於別名,shell函數和shell變量。
    • 一般來說,這是一個特性 ,因為Python(CPython)本身可以通過環境變量進行控制(對於2.x,請參閱https://docs.python.org/2/using/cmdline.html#environment-variables ;對於3.x,請參閱https://docs.python.org/3/using/cmdline.html#environment-variables )。
    • 如果需要,您可以通過env參數為shell 提供自己的環境 ; 但請注意, 您必須在該事件中提供整個環境 ,如果需要,可能包括USERHOME等變量; 簡單的例子,明確定義$PATH
    • subprocess.call('echo $PATH', shell = True, \\ env = { 'PATH': '/sbin:/bin:/usr/bin' })

shell為進程執行I / O重定向。 根據您的說法, subprocess模塊不會像這樣進行I / O重定向。 要演示,請運行:

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

它運行shell並應重定向I / O. 使用您的代碼,您的程序./x將被賦予一個它忽略的參數<inp.txt

注意:對subprocess.call的替代調用純粹是出於診斷目的,而不是推薦的解決方案。 推薦的解決方案包括閱讀(Python 2) 子流程模塊文檔(或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"))

默認情況下, subprocess模塊不會將參數傳遞給shell。 為什么? 因為通過shell運行命令是危險的 ; 除非它們被正確引用和轉義(這很復雜),否則通常可以說服執行此類操作的程序運行不需要的和意外的shell命令。

無論如何,使用shell都是錯誤的。 如果要從特定文件獲取輸入,可以使用subprocess.Popen ,將stdin參數設置為文件inp.txt (可以通過調用fileno()獲取文件描述符Python文件對象)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM