從腳本編寫到面向?qū)ο蟮腜ython編程

Python 在近年來的受歡迎程度劇增,部分原因在于該語言非常靈活,同時功能非常強大。Python 可用于系統(tǒng)管理、Web 開發(fā)、GUI 編程、科學計算等等。本文的主要目標是向習慣于使用 Bash、PHP 或其它某種語言編寫腳本過程代碼的人介紹面向?qū)ο蟮?Python 開發(fā),并幫助他們轉(zhuǎn)換到面向?qū)ο蟮?Python 開發(fā)。Python 的這種日益流行性意味著,對于目前使用其他編程語言的開發(fā)人員,除了使用他們最喜歡的語言之外,他們還可以采用 Python 來完成某些項目。

過程式編程當然有其用武之地,并且可能是解決某個問題的高度有效的方法。在非?;镜膶哟紊?,過程式編程可定義為指令的列表,Bash 和 PHP 通常就是以這樣的方式編寫的。然而由于 Python 的流行,對于作為 Web 開發(fā)人員或系統(tǒng)管理員的 PHP 和 Bash 腳本編寫人員,他們正陷入必須同時學習面向?qū)ο蟮木幊毯?Python 的境地。

面向?qū)ο筮@個概念很難一次性地掌握,因此本文采用過程式 Bash 和 PHP 腳本,并首先將它們轉(zhuǎn)換為過程式 Python。作為最后一步,它們將轉(zhuǎn)換為面向?qū)ο蟮?Python 這個終結目標。本文在結束時將簡略討論一下面向?qū)ο蟮?Python 的一些優(yōu)點,然后在最后討論一些可能更適合采用過程或函數(shù)式編程的一些不利場景。到本文結束時,Bash 或 PHP 程序員應該能夠毫無畏懼地一頭扎進面向?qū)ο蟮?Python 項目。

采用 PHP 和 Bash 編寫磁盤監(jiān)視函數(shù)

雖然 PHP 主要是為了在瀏覽器中運行,但是也可以通過 exec 函數(shù)執(zhí)行系統(tǒng)調(diào)用。采用 PHP 編寫的第一個示例將捕獲 Shell 命令“df –h”的輸出,將輸出放在一個數(shù)組中,然后根據(jù)一個正則表達式檢查輸出的每一行。如果該行與正則表達式匹配,則打印該行。如果您希望從主目錄運行此示例,只需將此腳本命名為 index.php,并將其放在 Apache/mod_php 服務器的對外服務目錄中。

PHP 磁盤監(jiān)視示例


//Analyzes disk usage

//Takes regex pattern and message

function disk_space( $pattern="/2[0-9]%/", $message="CAPACITY WARNING:" )

{

exec(escapeshellcmd("df -h"),$output_lines,$return_value);

foreach ($output_lines as $output) {

if (preg_match( $pattern, $output ))

echo "$message $output

";

}

}

disk_space()

?>

復制代碼

如果您在瀏覽器中運行此網(wǎng)頁,將會獲得以下結果:

CAPACITY WARNING: /dev/sda1 3.8G 694M 2.9G 20% /

查看該代碼,可以看到正則表達式模式被設置為匹配某個包含 20-29% 的行??梢匀菀椎匦薷拇四J揭赃m應其他標志,例如 90-99%,因為 20% 是非常低的磁盤容量。

下面讓我們看一下如何在 Bash 函數(shù)中完成同樣的事情。在 Bash 中,該問題要容易解決得多,因為您實際上是在處理系統(tǒng)調(diào)用。在此示例中,您甚至不需要使用數(shù)組或正則表達式庫,因為使用到 grep 的管道容易多了。不過,在 Bash 中設置函數(shù)的缺省參數(shù)始終有點麻煩。

Bash 磁盤監(jiān)視示例

#!/usr/bin/env bash

#function flags disk usage takes pattern and message optionally

function disk_space ()

{

#checks for pattern parameter

if [ "$1" != "" ]; then

pattern=$1

else

pattern="2[0-9]%"

fi

#checks for message parameter

if [ "$2" != "" ]; then

message=$2

else

message="CAPACITY WARNING:"

fi

#looks at output for pattern to flag

output_lines=`df -h | grep $pattern`

if [ "$output_lines" != "" ]; then

echo $message $output_lines

fi

}

#example of optional parameters usage

#disk_space 9[0-9]% ALERT:

disk_space

復制代碼

當您運行此腳本時,將會獲得同樣的輸出,因此可以跳過輸出的顯示。您能夠從該腳本的 PHP 版本和 Bash 版本中找到的相關性在于,此過程式代碼事實上像一組指令一樣運行。似乎計算機就像是一個小孩,而您告訴該小孩如何做某件事情,例如第一次系鞋帶。在您開始在 Python 中考慮“面向?qū)ο蠓妒健敝埃屛覀兪紫瓤匆幌氯绾尾捎?Python 來創(chuàng)建這同一個腳本的過程式版本。

Python 磁盤監(jiān)視示例

from subprocess import Popen, PIPE

import re

def disk_space(pattern="2[0-9]%", message="CAPACITY WARNING:"):

#takes shell command output

ps = Popen("df -h", shell=True,stdout=PIPE, stderr=PIPE)

output_lines = ps.stdout.readlines()

for line in output_lines():

line = line.strip()

if re.search(pattern,line):

print "%s %s" % (message,line)

disk_space()

復制代碼

瀏覽一下我們的代碼的過程式 Python 版本,發(fā)現(xiàn)它與 Bash 和 PHP 版本非常相似。對于 Python,子過程模塊處理對 Shell 命令的系統(tǒng)調(diào)用,并將輸出發(fā)在一個列表(在 Bash 和 PHP 中稱為數(shù)組)中。與 PHP 版本非常相似,然后我對命令的標準輸出行列表中的項進行了迭代遍歷。我尋找構成所尋找模式的正則表達式,然后使用注入的特殊消息來打印該磁盤報告行。這是如何解決自頂向下的腳本問題的經(jīng)典示例,但是在下一個部分中,您將完全改變這種方法,并從對象的角度考慮問題。

從過程到面向?qū)ο蟮?Python

過程式編程通常是初學的開發(fā)人員的最自然編程風格,并且對于許多問題來說也是高度有效的。另一方面,對于創(chuàng)建抽象從而創(chuàng)建可重用的代碼來說,面向?qū)ο蟮木幊炭赡苁欠浅S杏玫姆椒?。然而,當項目達到某種程度的復雜性之后,過程代碼通常會暴露出其根本缺陷。下面讓我們直接進入上一個示例的面向?qū)ο蟀姹荆⒖纯催@樣有何變化。

面向?qū)ο蟮?Python 磁盤監(jiān)視腳本

#!/usr/bin/env python

from subprocess import Popen, PIPE

import re

class DiskMonitor():

"""Disk Monitoring Class"""

def __init__(self,

pattern="2[0-9]%",

message="CAPACITY WARNING",

cmd = "df -h"):

self.pattern = pattern

self.message = message

self.cmd = cmd

def disk_space(self):

"""Disk space capacity flag method"""

ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE)

output_lines = ps.stdout.readlines()

for line in output_lines:

line = line.strip()

if re.search(self.pattern,line):

print "%s %s" % (self.message,line)

if __name__ == "__main__":

d = DiskMonitor()

d.disk_space()

復制代碼

查看該代碼的面向?qū)ο蟀姹荆梢钥吹酱a變得更加抽象。有時,太多的抽象會導致設計問題,但是在此例中,它允許您將問題分離為更多可重用的部分。 DiskMonitor 類具有 __init__ method,您可以在其中定義新的參數(shù),并且 disk_space 函數(shù)現(xiàn)在是該類中的一個方法。

使用這種新的樣式,您無需更改原始代碼即可容易地重用和自定義各個部分,而使用過程代碼時則通常必須更改原始代碼。面向?qū)ο蟮脑O計的一個更加功能強大、通常也被過度使用的方面是繼承。繼承允許您在新的類中重用和自定義現(xiàn)有的代碼。讓我們在下一個示例中看看繼承可能像什么樣子。

使用繼承的面向?qū)ο?Python 磁盤監(jiān)視腳本

#!/usr/bin/env python

from subprocess import Popen, PIPE

import re

class DiskMonitor():

"""Disk Monitoring Class"""

def __init__(self,

pattern="2[0-9]%",

message="CAPACITY WARNING",

cmd = "df -h"):

self.pattern = pattern

self.message = message

self.cmd = cmd

def disk_space(self):

"""Disk space capacity flag method"""

ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE)

output_lines = ps.stdout.readlines()

for line in output_lines:

line = line.strip()

if re.search(self.pattern,line):

print "%s %s" % (self.message,line)

class MyDiskMonitor(DiskMonitor):

"""Customized Disk Monitoring Class"""

def disk_space(self):

ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE)

print "RAW DISK REPORT:"

print ps.stdout.read()

if __name__ == "__main__":

d = MyDiskMonitor()

d.disk_space()

復制代碼

如果運行這個使用繼承的腳本版本,您將獲得以下輸出:

RAW DISK REPORT:

Filesystem? ?? ?? ?? ?Size??Used Avail Use% Mounted on

/dev/sda1? ?? ?? ?? ? 3.8G??694M??2.9G??20% /

varrun? ?? ?? ?? ?? ? 252M? ?48K??252M? ?1% /var/run

varlock? ?? ?? ?? ?? ?252M? ???0??252M? ?0% /var/lock

udev? ?? ?? ?? ?? ?? ?252M? ?52K??252M? ?1% /dev

devshm? ?? ?? ?? ?? ? 252M? ???0??252M? ?0% /dev/shm

此輸出與前面帶標記的版本區(qū)別非常大,因為它只是使用頂部注入的 print 語句來打印的未經(jīng)篩選的 df –h 命令結果。通過重寫 MyDiskMonitor 類中的方法,您能夠完全改變 disk_space 方法的意圖。

允許您重用其他類中的屬性的 Python 魔法是這個“MyDiskMonitor(DiskMonitor)”語句。您只需在定義新類的名稱時,將先前的類的名稱放在括號內(nèi)。一旦完成此步驟,您立即可以訪問其他類屬性來做自己希望的事情。但是樂趣不僅于此。通過添加另一個通過電子郵件來發(fā)送標記消息的方法,也許是將其命名為 disk_alert(self),這樣就可以進一步自定義新類。這是面向?qū)ο蟮脑O計的美妙之處;它允許有經(jīng)驗的開發(fā)人員不斷重用已編寫的代碼,從而節(jié)省大量的時間。

遺憾的是,面向?qū)ο蟮木幊桃灿衅洳焕囊幻?。所有這些抽象都是以復雜性為代價的,如果抽象過度,可能會徹底地弄巧成拙。由于 Python 支持多重繼承,抽象可以達到相當有害的復雜程度。您是否能夠想象只是為了編寫一個方法也要查看多個文件的情況?無論相信與否,這種情況的確會發(fā)生,并且代表了面向?qū)ο缶幊痰牟恍椰F(xiàn)實。

面向?qū)ο蟮木幊痰奶娲桨甘呛瘮?shù)式編程,并且 Python 提供了用于進行函數(shù)式以及面向?qū)ο蠛瓦^程式編程的資源。在最后一個示例中,我們將研究如何以函數(shù)式的方式編寫現(xiàn)已變得非常無聊的磁盤監(jiān)視代碼。

函數(shù)式的 Python 磁盤監(jiān)視腳本

from subprocess import Popen, PIPE

import re

def disk_space(pattern="2[0-9]%", message="CAPACITY WARNING:"):

#Generator Pipeline To Search For Critical Items

ps = Popen("df -h", shell=True,stdout=PIPE, stderr=PIPE)

outline = (line.split() for line in ps.stdout)

flag = (" ".join(row) for row in outline if re.search(pattern, row[-2]))

for line in flag:

print "%s %s" % (message,line)

disk_space()

復制代碼

查看這最后一個示例,它與您從本文中看到的所有其他代碼的區(qū)別都非常大。如果您逐行瀏覽該代碼,可以首先從 “ps”變量中以前未見過的內(nèi)容開始。接下來的兩行代碼使用生成器表達式來處理文件對象 ps.stdout,分析該文件并在其中搜索您正在查找的行。如果您將這些代碼行剪切并粘貼到交互式的 Python Shell 中,如果打印的話,您將看到概要和標志都是生成器對象。生成器對象附帶有下一個方法,因而允許您通過“管道”將操作連在一起。

概要行從一行中去除新行字符,并往下將該行傳遞給下一個生成器表達式,后者一次一個地在每行中搜索某個正則表達式匹配項,然后將輸出傳遞給標記。此類緊湊的工作流可以替代面向?qū)ο蟮木幊虡邮剑⑶蚁喈斢腥?。然而,這種樣式也有缺點,因為代碼的簡潔性會導致難于調(diào)試的錯誤,除非獨立地執(zhí)行每一行代碼。函數(shù)式編程還很傷腦筋,因為它讓您通過將解決方案鏈接在一起來考慮解決問題。無論是從過程式還是從面向?qū)ο髽邮降慕嵌瓤?,這都是相當不同的。

總結

本文有點試驗性質(zhì),因為它從 Bash 和 PHP 談到了過程、面向?qū)ο?,并在最后談到了使用相同基本代碼的函數(shù)式 Python。但愿本文說明了 Python 是一種非常靈活和功能強大的語言,其他編程語言的開發(fā)人員也可以學習欣賞。隨著 Python 的越來越流行,其他開發(fā)人員除了首選語言之外,學習 Python 也將變得更加重要。

Python 最近的兩個最大的發(fā)展領域是 Web 開發(fā)和系統(tǒng)管理。就 Web 開發(fā)而言,PHP 開發(fā)人員可能很快就必須做出每周的選擇,即哪個項目采用 Python 更有意義,以及哪個項目采用 PHP 更有意義。對于系統(tǒng)管理員、Bash 和 Perl 腳本程序員,他們經(jīng)常被要求采用 Python 完成某些項目。部分是因為這是沒有選擇的,部分是因為許多供應商正在為他們的產(chǎn)品提供 Python API。在您的工具箱中準備一點 Python 決不會傷害任何人。學好python你需要一個良好的環(huán)境,一個優(yōu)質(zhì)的開發(fā)交流群,群里都是那種相互幫助的人才是可以的,我有建立一個python學習交流群,在群里我們相互幫助,相互關心,相互分享內(nèi)容,這樣出問題幫助你的人就比較多,群號是301,還有056,最后是051,這樣就可以找到大神聚合的群,如果你只愿意別人幫助你,不愿意分享或者幫助別人,那就請不要加了,你把你會的告訴別人這是一種分享。

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

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

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,511評論 19 139
  • 1.創(chuàng)建文件夾 !/bin/sh mkdir -m 777 "%%1" 2.創(chuàng)建文件 !/bin/sh touch...
    BigJeffWang閱讀 10,482評論 3 53
  • 背景: 閱讀新聞 12C CDB模式下RMAN備份與恢復 [日期:2016-11-29] 來源:Linux社區(qū) 作...
    陽屯okyepd閱讀 3,828評論 0 7
  • 陽臺的花盆,還空著一個。 怪可惜的,思量著養(yǎng)點植物放在里面。嬌嫩的花卉養(yǎng)不起,也養(yǎng)不活,見著小區(qū)的荒地上,長著不少...
    周世恩閱讀 2,296評論 1 10
  • 你是不是很想遇見一位高人可以教你寫作呢? 1. 寫作就是一次與高人的走心交流。 為什么不說閱讀是一次高人交流呢? ...
    燁然v閱讀 996評論 6 20

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