用Python代替shell腳本

Python和shell script是目前編寫腳本類應用的不二之選,在糾結使用Python還是shell script時,希望本文能夠提供一些思路。

Python和shell script對比

Python最突出的優(yōu)勢在于語言相對簡單,熟悉的人多,支持json解析等高級語言特性。

shell的優(yōu)勢在于特定場景下代碼更簡練,ps,grep,awk,sed,tar等命令一行能夠搞定的場景,如果用python原生代碼來實現(xiàn)相對會比較復雜,而且往往還需要安裝第三方Python庫。

在部署方式上兩者區(qū)別都不大,python和shell大部分情況下使用“原生庫”即可搞定。

Python的原生庫subprocess支持調(diào)用shell script命令,選擇Python + subprocess庫的方案可以結合兩者的優(yōu)勢,這是我為什么推薦用Python代替shell腳本的原因

subprocess注意事項

兼容性

subprocess庫有多個版本,需兼容不同的版本。核心代碼如下:

def check_output(cmd):
    """
    execute shell commandline, return output
    :param cmd: commandline string
    :return:
        output string: empty string if output nothing. For shell command, the output has a "\n" in the end generally.
        None: failed to execute the commandline, do not use None to judge whether the execution result is ok.
    """
    if hasattr(subprocess, 'check_output'):
        try:
            p = subprocess.check_output(cmd, shell=True)
            if isinstance(p, bytes):
                return p.decode()
            else:
                return p
        except subprocess.CalledProcessError as e:
            print(e)
            return None
    else:
        # python version < 2.7
        try:
            output = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=True).communicate()[0]
            return output
        except subprocess.CalledProcessError as e:
            print(e)
            return None

grep命令的返回值

grep查找失敗時,subprocess在python3中會直接拋出異常,這與shell的習慣不同。以如下代碼舉例:

if grep abc check_process.sh ;
then
        echo good
fi

這是shell中的典型寫法,判斷check_process.sh文件中是否存在abc字符串,使用subprocess實現(xiàn)的話,代碼一般如下:

if __name__ == "__main__":
    r = check_output("grep abc check_process.sh")
        if "abc" in r:
            print "good"

當grep查找失敗時,返回值是1。在python3中會拋出異常,返回None,而不是空字符串,此時在命令尾部增加 “|| true”即可,請注意在這種情況下,即使命令執(zhí)行失敗也不會返回None,比如check_process.sh不存在時也會返回空字符串。

r = check_output("grep abc check_process.sh || true")

非預期輸出

命令的輸出會與腳本輸出混雜在一起,比如grep的結果會直接輸出到stdout。我們當然可以通過重定向到/dev/null的方式來處理,但是總會有漏網(wǎng)之魚。如果腳本最終要輸出格式化的數(shù)據(jù),建議輸出到文件中,而不是stdout。

最佳實踐推薦

  1. Python中調(diào)用subprocess集成shell腳本
  2. 使用單元測試
  3. 使用getopt庫處理入?yún)?/li>
  4. 支持格式化輸出,比如json。結果輸出到文件,而不僅僅是stdout。
  5. 關注腳本的退出code, sys.exit()返回值應體現(xiàn)出腳本執(zhí)行結果。

如果對你有幫助,請順手點個贊

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容