1. 程式人生 > >Linux 平臺下 Python 指令碼程式設計入門(二)

Linux 平臺下 Python 指令碼程式設計入門(二)

在“Linux 平臺下 Python 指令碼程式設計入門”系列之前的文章裡,我們向你介紹了 Python 的簡介,它的命令列 shell 和 IDLE(LCTT 譯註:python 自帶的一個 IDE)。我們也演示瞭如何進行算術運算、如何在變數中儲存值、還有如何列印那些值到螢幕上。最後,我們通過一個練習示例講解了面向物件程式設計中方法和屬性概念。

 Python 指令碼程式設計

在 Python 程式設計中寫 Linux Shell 指令碼

本篇中,我們會討論控制流(根據使用者輸入的資訊、計算的結果,或者一個變數的當前值選擇不同的動作行為)和迴圈(自動重複執行任務),接著應用我們目前所學東西來編寫一個簡單的 shell 指令碼,這個指令碼會顯示作業系統型別、主機名、核心版本、版本號和機器硬體架構。

這個例子儘管很基礎,但是會幫助我們證明,比起使用一般的 bash 工具,我們通過發揮 Python 面向物件的特性來編寫 shell 指令碼會更簡單些。

換句話說,我們想從這裡出發:

  1. # uname -snrvm

 Python 指令碼程式設計

檢查 Linux 的主機名

 Python 指令碼程式設計

用 Python 指令碼來檢查 Linux 的主機名

或者

Python 指令碼程式設計

用指令碼檢查 Linux 系統資訊

看著不錯,不是嗎?那我們就挽起袖子,開幹吧。

Python 中的控制流

如我們剛說那樣,控制流允許我們根據一個給定的條件,選擇不同的輸出結果。在 Python 中最簡單的實現就是一個if/else 語句。

基本語法是這樣的:

  1. if 條件:
  2. # 動作
    1
  3. else:
  4. # 動作 2

當“條件”求值為真(true),下面的程式碼塊就會被執行(# 動作 1代表的部分)。否則,else 下面的程式碼就會執行。 “條件”可以是任何表示式,只要可以求得值為真或者假。

舉個例子:

  1. 1 < 3 # 真
  2. firstName == "Gabriel" # 對 firstName 為 Gabriel 的人是真,對其他不叫 Gabriel 的人為假
  • 在第一個例子中,我們比較了兩個值,判斷 1 是否小於 3。
  • 在第二個例子中,我們比較了 firstName(一個變數)與字串 “Gabriel”,看在當前執行的位置,firstName 的值是否等於該字串。
  • 條件和 else 表示式都必須跟著一個冒號(:)。
  • 縮排在 Python 中非常重要。同樣縮排下的行被認為是相同的程式碼塊。

請注意,if/else 表示式只是 Python 中許多控制流工具的一個而已。我們先在這裡瞭解以下,後面會用在我們的指令碼中。你可以在官方文件[1]中學到更多工具。

Python 中的迴圈

簡單來說,一個迴圈就是一組指令或者表示式序列,可以按順序一直執行,只要條件為真,或者對列表裡每個專案執行一一次。

Python 中最簡單的迴圈,就是用 for 迴圈迭代一個給定列表的元素,或者對一個字串從第一個字元開始到執行到最後一個字元結束。

基本語句:

  1. for x in example:
  2. # do this

這裡的 example 可以是一個列表或者一個字串。如果是列表,變數 x 就代表列表中每個元素;如果是字串,x 就代表字串中每個字元。

  1. >>> rockBands = []
  2. >>> rockBands.append("Roxette")
  3. >>> rockBands.append("Guns N' Roses")
  4. >>> rockBands.append("U2")
  5. >>> for x in rockBands:
  6. print(x)
  7. >>> firstName = "Gabriel"
  8. >>> for x in firstName:
  9. print(x)

上面例子的輸出如下圖所示:

Linux 平臺

學習 Python 中的迴圈

Python 模組

很明顯,必須有個辦法將一系列的 Python 指令和表示式儲存到檔案裡,然後在需要的時候取出來。

準確來說模組就是這樣的。比如,os 模組提供了一個到作業系統的底層的介面,可以允許我們做許多通常在命令列下執行的操作。

沒錯,os 模組包含了許多可以用來呼叫的方法和屬性,就如我們之前文章裡講解的那樣。不過,我們需要使用 import關鍵詞匯入(或者叫包含)模組到執行環境裡來:

  1. >>> import os

我們來打印出當前的工作目錄:

  1. >>> os.getcwd()

Linux 平臺

學習 Python 模組

現在,讓我們把這些結合在一起(包括之前文章裡討論的概念),編寫需要的指令碼。

Python 指令碼

以一段宣告文字開始一個指令碼是個不錯的想法,它可以表明指令碼的目的、釋出所依據的許可證,以及一個列出做出的修改的修訂歷史。儘管這主要是個人喜好,但這會讓我們的工作看起來比較專業。

這裡有個指令碼,可以輸出這篇文章最前面展示的那樣。指令碼做了大量的註釋,可以讓大家可以理解發生了什麼。

在進行下一步之前,花點時間來理解它。注意,我們是如何使用一個 if/else 結構,判斷每個欄位標題的長度是否比欄位本身的值還大。

基於比較結果,我們用空字元去填充一個欄位標題和下一個之間的空格。同時,我們使用一定數量的短線作為欄位標題與其值之間的分割符。

  1. #!/usr/bin/python3
  2. # 如果你沒有安裝 Python 3 ,那麼修改這一行為 #!/usr/bin/python
  3. # Script name: uname.py
  4. # Purpose: Illustrate Python OOP capabilities to write shell scripts more easily
  5. # License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
  6. # Copyright (C) 2016 Gabriel Alejandro Cánepa
  7. # Facebook / Skype / G+ / Twitter / Github: gacanepa
  8. # Email: gacanepa (at) gmail (dot) com
  9. # This program is free software: you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation, either version 3 of the License, or
  12. # (at your option) any later version.
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
  16. # GNU General Public License for more details.
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program.If not, see .
  19. # REVISION HISTORY
  20. # DATE        VERSION AUTHOR         CHANGE DESCRIPTION
  21. # ---------- ------- --------------
  22. # 2016-05-28 1.0Gabriel Cánepa    Initial version
  23. ### 匯入 os 模組
  24. import os
  25. ### 將 os.uname() 的輸出賦值給 systemInfo 變數
  26. ### os.uname() 會返回五個字串元組(sysname, nodename, release, version, machine)
  27. ### 參見文件:https://docs.python.org/3.2/library/os.html#module-os
  28. systemInfo = os.uname()
  29. ### 這是一個固定的陣列,用於描述指令碼輸出的欄位標題
  30. headers = ["Operating system","Hostname","Release","Version","Machine"]
  31. ### 初始化索引值,用於定義每一步迭代中
  32. ### systemInfo 和欄位標題的索引
  33. index = 0
  34. ### 欄位標題變數的初始值
  35. caption = ""
  36. ### 值變數的初始值
  37. values = ""
  38. ### 分隔線變數的初始值
  39. separators = ""
  40. ### 開始迴圈
  41. for item in systemInfo:
  42. if len(item) < len(headers[index]):
  43. ### 一個包含橫線的字串,橫線長度等於item[index] 或 headers[index]
  44. ### 要重複一個字元,用引號圈起來並用星號(*)乘以所需的重複次數
  45.     separators = separators + "-" * len(headers[index]) + " "
  46.     caption = caption + headers[index] + " "
  47.     values = values + systemInfo[index] + " " * (len(headers[index]) - len(item)) + " "
  48. else:
  49.     separators = separators + "-" * len(item) + " "
  50.     caption =  caption + headers[index] + " " * (len(item) - len(headers[index]) + 1)
  51.     values = values + item + " "
  52. ### 索引加 1
  53.    index = index + 1
  54. ### 終止迴圈
  55. ### 輸出轉換為大寫的變數(欄位標題)名
  56. print(caption.upper())
  57. ### 輸出分隔線
  58. print(separators)
  59. # 輸出值(systemInfo 中的專案)
  60. print(values)
  61. ### 步驟:
  62. ### 1) 保持該指令碼為 uname.py (或任何你想要的名字)
  63. ### 並通過如下命令給其執行許可權:
  64. ### chmod +x uname.py
  65. ### 2) 執行它;
  66. ### ./uname.py

如果你已經按照上述描述將上面的指令碼儲存到一個檔案裡,並給檔案增加了執行許可權,那麼執行它:

  1. # chmod +x uname.py
  2. # ./uname.py

如果試圖執行指令碼時你得到了如下的錯誤:

  1. -bash: ./uname.py: /usr/bin/python3: bad interpreter: No such file or directory

這意味著你沒有安裝 Python3。如果那樣的話,你要麼安裝 Python3 的包,要麼替換直譯器那行(如果如之前文章裡概述的那樣,跟著下面的步驟去更新 Python 執行檔案的軟連線,要特別注意並且非常小心):

  1. #!/usr/bin/python3

  1. #!/usr/bin/python

這樣會通過使用已經安裝好的 Python 2 去執行該指令碼。

注意:該指令碼在 Python 2.x 與 Pyton 3.x 上都測試成功過了。

儘管比較粗糙,你可以認為該指令碼就是一個 Python 模組。這意味著你可以在 IDLE 中開啟它(File → Open… → Select file):

Linux 平臺

在 IDLE 中開啟 Python

一個包含有檔案內容的新視窗就會開啟。然後執行 Run → Run module(或者按 F5)。指令碼的輸出就會在原始的 Shell 裡顯示出來:

Linux 平臺

執行 Python 指令碼

如果你想純粹用 bash 寫一個指令碼,也獲得同樣的結果,你可能需要結合使用 awk[2]sed[3],並且藉助複雜的方法來儲存與獲得列表中的元素(不要忘了使用 tr 命令將小寫字母轉為大寫)。

另外,在所有的 Linux 系統版本中都至少集成了一個 Python 版本(2.x 或者 3.x,或者兩者都有)。你還需要依賴 shell 去完成同樣的目標嗎?那樣你可能需要為不同的 shell 編寫不同的版本。

這裡演示了面向物件程式設計的特性,它會成為一個系統管理員得力的助手。

注意:你可以在我的 Github 倉庫裡獲得 這個 python 指令碼[4](或者其他的)。

總結

這篇文章裡,我們講解了 Python 中控制流、迴圈/迭代、和模組的概念。我們也演示瞭如何利用 Python 中面向物件程式設計的方法和屬性來簡化複雜的 shell 指令碼。

你有任何其他希望去驗證的想法嗎?開始吧,寫出自己的 Python 指令碼,如果有任何問題可以諮詢我們。不必猶豫,在分割線下面留下評論,我們會盡快回復你。

本文由 LCTT[8] 原創編譯

文章出處:Linux中國

[1]: http://please%20note%20that%20the%20if%20/%20else%20statement%20is%20only%20one%20of%20the%20many%20control%20flow%20tools%20available%20in%20Python.%20We%20reviewed%20it%20here%20since%20we%20will%20use%20it%20in%20our%20script%20later.%20You%20can%20learn%20more%20about%20the%20rest%20of%20the%20tools%20in%20the%20official%20docs.
[2]: http://www.tecmint.com/use-linux-awk-command-to-filter-text-string-in-files/
[3]: http://www.tecmint.com/sed-command-to-create-edit-and-manipulate-files-in-linux/
[4]: https://github.com/gacanepa/scripts/blob/master/python/uname.py
[5]: http://www.tecmint.com/author/gacanepa/
[6]: https://github.com/wi-cuckoo
[7]: https://github.com/wxy
[8]: https://github.com/LCTT/TranslateProject
[9]: https://linux.cn/