您好,登錄后才能下訂單哦!
這篇文章主要介紹了怎么用Python擴(kuò)展和延伸Nautilus,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Nautilus 腳本
擴(kuò)展 Nautilus 的第一個(gè)方法是通過(guò)在 /home 中發(fā)現(xiàn)的名為 .gnome2/nautilus-scripts 的特定目錄。當(dāng)在 Scripts 菜單下的文件或者文件夾上點(diǎn)擊鼠標(biāo)右鍵時(shí),該目錄下所有可執(zhí)行文件將會(huì)出現(xiàn)。還可以選擇多個(gè)文件或者文件夾,并采用相同的右擊方法,將文件清單傳遞給腳本。
當(dāng)調(diào)用腳本時(shí),Nautilus 支持多個(gè)包含當(dāng)前目錄以及所選文件等內(nèi)容的環(huán)境變量。表 1 展示了這些環(huán)境變量。
表 1. Nautilus 環(huán)境變量
環(huán)境變量 | 描述 |
NAUTILUS_SCRIPT_SELECTED_FILE_PATHS | 所選文件的新行分割路徑(僅針對(duì)本地) |
NAUTILUS_SCRIPT_SELECTED_URIS | 所選文件的新行分割 URIs |
NAUTILUS_SCRIPT_CURRENT_URI | 當(dāng)前位置 |
NAUTILUS_SCRIPT_WINDOW_GEOMETRY | 當(dāng)前窗口的位置和大小 |
在 Python 中,通過(guò)對(duì) os.environ.get 函數(shù)的一個(gè)調(diào)用來(lái)獲取這些變量的值,具體如下:
selected = os.environ.get('NAUTILUS_SCRIPT_SELECTED_FILE_PATHS,'')
此調(diào)用返回一個(gè)字符串,其包含到達(dá)由換行符分隔的全部所選文件。Python 利用下列代碼,簡(jiǎn)化了將這一字符串返回到可迭代列表中的操作:
targets = selected.splitlines()
此時(shí),也許應(yīng)該停下來(lái)探討一下用戶交互。當(dāng)控制從 Nautilus 傳送到腳本后,在該點(diǎn)上確實(shí)不存在對(duì)腳本的限制。根據(jù)腳本作用的不同,甚至不需要任何用戶反饋,除了一些類(lèi)型的完成或錯(cuò)誤消息,這樣通過(guò)一些簡(jiǎn)單的消息框就可處理好。由于在編寫(xiě) Nautilus 時(shí)采用了 gtk windowing 工具包,所以盡管這不是必須的,但是采用相同的做法很合乎邏輯。您可以很方便地使用 TkInter 或者 wxPython。
鑒于本文的目的,您將采用 gtk。生成一個(gè)用于通信完成狀態(tài)的簡(jiǎn)單消息框,僅需幾行代碼,出于方便閱讀的目的,如果想創(chuàng)建簡(jiǎn)單的函數(shù)來(lái)生成消息,這個(gè)代碼將最為合適。總共需要 4 行代碼:
def alert(msg): dialog = gtk.MessageDialog() dialog.set_markup(msg) dialog.run()
示例:創(chuàng)建簡(jiǎn)單腳本來(lái)返回所選文件的數(shù)量
第一個(gè)示例程序?qū)⒍鄠€(gè)程序段合并成一個(gè)簡(jiǎn)單腳本,來(lái)返回當(dāng)前所選文件的數(shù)量。這一腳本可用于文件或者目錄。可利用另一個(gè) Python 庫(kù)函數(shù),os.walk,遞歸地構(gòu)建每個(gè)目錄中文件的清單??偣灿?38 行代碼,如清單 1 所示,這就是這一小工具所需的全部?jī)?nèi)容,其中還包括了空行。
清單 1. 用于 Filecount 腳本的 代碼 Python
#!/usr/bin/env python import pygtk pygtk.require('2.0') import gtk import os def alert(msg): """Show a dialog with a simple message.""" dialog = gtk.MessageDialog() dialog.set_markup(msg) dialog.run() def main(): selected = os.environ.get('NAUTILUS_SCRIPT_SELECTED_URIS', '') curdir = os.environ.get('NAUTILUS_SCRIPT_CURRENT_URI', os.curdir) if selected: targets = selected.splitlines() else: targets = [curdir] files = [] directories = [] for target in targets: if target.startswith('file:///'): target = target[7:] for dirname, dirnames, filenames in os.walk(target): for dirname in dirnames: directories.append(dirname) for filename in filenames: files.append(filename) alert('%s directories and %s files' % (len(directories),len(files))) if __name__ == "__main__": main()
圖 1 展示了當(dāng)在文件上右擊鼠標(biāo)或者選擇一組文件時(shí)所看到的內(nèi)容。Scripts 菜單選項(xiàng)展示 .gnome2/nautilus-scripts 中所有的可執(zhí)行文件,并給出了打開(kāi)文件夾的選項(xiàng)。選擇一個(gè)文件來(lái)執(zhí)行該腳本。
圖 1.在 Nautilus 中選擇文件
圖 2 展示了 Filecount.py 腳本的運(yùn)行結(jié)果。
圖 2. Filecount.py 輸出
在調(diào)試 Nautilus 腳本時(shí),有幾件事需要注意。第一件事是關(guān)閉 Nautilus 的所有實(shí)例,來(lái)使它完全重新加載,并找到新腳本或者擴(kuò)展??刹捎萌缦旅睿?/p>
nautilus -q
下一個(gè)常用命令可實(shí)現(xiàn)不必打開(kāi)首選或者配置數(shù)據(jù),而直接運(yùn)行 Nautilus。這在解決腳本或者擴(kuò)展在無(wú)意間造成破壞之類(lèi)的問(wèn)題時(shí),會(huì)節(jié)省很多步驟。命令如下:
nautilus -no-desktop
確保 filecount 工具可被 Nautilus 訪問(wèn)所剩的最后一步是將其復(fù)制到 ~/.gnome2/nautilus-scripts 目錄,并改變文件代碼來(lái)允許執(zhí)行,相關(guān)命令是:
chmod +x Filecount.py
示例:創(chuàng)建文件 cleanup 工具
第二個(gè)例子是,創(chuàng)建文件 cleanup 工具,來(lái)查找任何可能由 Vim 或者 EMACS 之類(lèi)的編輯器臨時(shí)生成的文件。僅通過(guò)簡(jiǎn)單地修改 check 函數(shù),就可利用相同的概念來(lái)清除任何特定文件的目錄。這一代碼屬于靜默操作,這意味著它執(zhí)行后不向用戶提供任何反饋。
該腳本的主函數(shù)看上去基本與前面具的示例相同,除了幾個(gè)微不足道的異常。此代碼會(huì)利用遞歸概念多次調(diào)用主函數(shù),直至處理完最后一個(gè)目錄為止。您可以采用 os.walk 函數(shù),而不必采用遞歸來(lái)完成相同的任務(wù)。文件檢查發(fā)生在 check 函數(shù)中,僅簡(jiǎn)單地檢查以波浪號(hào)(~)或者井號(hào)(#)結(jié)束的文件,以井號(hào)后開(kāi)始或擴(kuò)展名 .pyc 結(jié)束的文件。該示例展示了 Python 標(biāo)準(zhǔn)庫(kù) os 模塊所提供的數(shù)量眾多的函數(shù)。它還提供了獨(dú)立于操作系統(tǒng)方式來(lái)操作路徑名和目錄,以及執(zhí)行文件操作的示例。清單 2 展示了該腳本的代碼。
清單 2. 用于 cleanup 腳本的 Python 代碼
#!/usr/bin/env python import pygtk pygtk.require('2.0') import gtk import os def check(path): """Returns true to indicate a file should be removed.""" if path.endswith('~'): return True if path.startswith('#') and basename.endswith('#'): return True if path.endswith('.pyc'): return True return False def walk(dirname=None): selected = os.environ.get('NAUTILUS_SCRIPT_SELECTED_FILE_PATHS', '') curdir = os.environ.get('NAUTILUS_SCRIPT_CURRENT_URI', os.curdir) if dirname is not None: targets = [dirname] elif selected: targets = selected.splitlines() else: targets = [curdir] for target in targets: if target.startswith('file:///'): target = target[7:] if not os.path.isdir(target): continue for dirname, dirnames, files in os.walk(target): for dir in dirnames: dir = os.path.join(dirname, dir) walk(dir) for file in files: file = os.path.join(dirname, file) if check(file): os.remove(file) if __name__ == '__main__': walk()
Nautilus 擴(kuò)展
增強(qiáng) Nautilus 的第二個(gè)方法是通過(guò)創(chuàng)建擴(kuò)展。此方法比第一個(gè)復(fù)雜,但有很多優(yōu)勢(shì)。Nautilus 擴(kuò)展可被內(nèi)嵌到文件展示窗口中,那么就可以編寫(xiě)利用以前沒(méi)有的信息來(lái)填充列的擴(kuò)展。首先要做的就是利用如下命令安裝 python-nautilus 擴(kuò)展:
sudo apt-get install python-nautilus
此命令下載并安裝所需的文件,包括文檔和示例。可在目錄 /usr/share/doc/python-nautilus/examples 中到找到示例代碼。安裝完成后,就可以訪問(wèn)一組 Nautilus 類(lèi)和提供程序來(lái)再次對(duì)其進(jìn)行編碼。表 2 展示了該清單。
表 2. Nautilus 類(lèi)與供應(yīng)商
類(lèi)或者供應(yīng)商 | 描述 |
nautilus.Column | 引用 Nautilus column 對(duì)象 |
nautilus.FileInfo | 引用 Nautilus fileinfo 對(duì)象 |
nautilus.Menu | 引用 Nautilus menu 對(duì)象 |
nautilus.MenuItem | 引用 Nautilus menuitem 對(duì)象 |
nautilus.PropertyPage | 引用 Nautilus propertypage 對(duì)象 |
nautilus.ColumnProvider | 允許在 Nautilus 列中展示輸出 |
nautilus.InfoProvider | 提供關(guān)于文件的信息 |
nautilus.LocationWidgetProvider | 展示位置 |
nautilus.MenuProvider | 為右擊菜單增加新功能 |
nautilus.PropertyPageProvider | 為屬性頁(yè)面增加信息 |
gnome.org 站點(diǎn)上提供的示例展示了 MenuProvider(background-image.py 和 open-terminal.py)、ColumnProvider 以及 InfoProvider(block-size-column.py)、和 PropertyPageProvider(md5sum-property-page.py)的使用。ColumnProvider 采用 13 行 Python 可執(zhí)行代碼來(lái)向 Nautilus 引入新的列。一旦該代碼被放置到合適的目錄中(~/.nautilus/python-extensions)并且 Nautilus 已重啟,在單擊 View > Visible Columns 時(shí)將會(huì)看到新的選項(xiàng)。當(dāng)將查看類(lèi)型設(shè)置為 List 時(shí),才會(huì)出現(xiàn) Visible Columns 選項(xiàng)。通過(guò)選擇展示以下 Python 庫(kù)調(diào)用結(jié)果的復(fù)選框,來(lái)啟用 Block size 列:
str(os.stat(filename).st_blksize))
任何 Python 擴(kuò)展的基本模式都是對(duì)現(xiàn)有 Nautilus 提供程序基本類(lèi)進(jìn)行子類(lèi)劃分,然后執(zhí)行一系列指令,并最終返回合適的 Nautilus 對(duì)象。在 block-size-column.py 例子中,返回的對(duì)象是 nautilus.Column。必須向 Nautilus 傳遞 4 個(gè)參數(shù),包括 name、attribute、label、以及 description。本例子的 Python 代碼是:
return nautilus.Column("NautilusPython::block_size_column", "block_size", "Block size", "Get the block size")
編寫(xiě)新擴(kuò)展的代碼涉及繼承來(lái)自特定基本類(lèi)的信息。 在 block-size-column.py 的例子中,nautilus.ColumnProvider 與 nautilus.InfoProvider 在類(lèi)定義中有舉例,因此新類(lèi)要從這兩處繼承。接下來(lái)需要覆蓋來(lái)自基類(lèi)或者類(lèi)的任何方法來(lái)填充列。在 block-size-column.py 例子中,可通過(guò)覆蓋 get_columns 和 update_file_info 方法來(lái)完成。
向 Nautilus 擴(kuò)展傳遞信息的方法與腳本示例不同。Nautilus 實(shí)際上是啟動(dòng)新的流程來(lái)執(zhí)行腳本,并設(shè)置多個(gè)環(huán)境變量來(lái)傳遞信息。在與 Nautilus 相同的流程中執(zhí)行的擴(kuò)展,能夠訪問(wèn)對(duì)象、方法、和屬性。通過(guò) nautilus.FileInfo 傳遞的文件信息,包括 file_type、location、name、uri、以及 mime_type。想要向 FileInfo 對(duì)象增加信息,必須調(diào)用 add_string_attribute 方法。下面的例子是采用這一方法,來(lái)向 FileInfo 對(duì)象增加新的屬性。
示例:列出了文件中的行數(shù)
第一個(gè)例子使用 PropertyPageProvider 方法在文件(或多個(gè)文件)上單擊右鍵顯示行數(shù)和參數(shù),然后單擊 Properties。這一擴(kuò)展背后的基本思想是計(jì)算文件中的行數(shù)和參數(shù)個(gè)數(shù),并在文件屬性頁(yè)的新選項(xiàng)卡中報(bào)告結(jié)果。擴(kuò)展可以直接訪問(wèn)了 Nautilus 數(shù)據(jù)結(jié)構(gòu),包括 file 對(duì)象。惟一要做的是利用 urllib.unquote 庫(kù)函數(shù)來(lái)打開(kāi)名字,操作如下:
filename = urllib.unquote(file.get_uri()[7:]
Python 中的一些行完成了對(duì)行及參數(shù)計(jì)數(shù)的主要工作。對(duì)于本例來(lái)說(shuō),創(chuàng)建 count 函數(shù)來(lái)將整個(gè)文件讀取到一個(gè)大字符串中,然后計(jì)算參數(shù)數(shù)量及新添參數(shù)數(shù)量。因?yàn)閷傩皂?yè)面可被顯示為很多選中的文件及目錄,所以必須預(yù)先計(jì)算多個(gè)文件。此時(shí),惟一要做的就是將結(jié)果添加到屬性頁(yè)上的新頁(yè)中。本例創(chuàng)建了示例 gtk.Hbox,然后利用獲取的信息來(lái)填充大量標(biāo)簽,如清單 3 所示。
清單 3. Linecountextension.py 文件
import nautilus import urllib import gtk import os types = ['.py','.js','.html','.css','.txt','.rst','.cgi'] exceptions = ('MochiKit.js',) class LineCountPropertyPage(nautilus.PropertyPageProvider): def __init__(self): pass def count(self, filename): s = open(filename).read() return s.count('\n'), len(s) def get_property_pages(self, files): if not len(files): return lines = 0 chars = 0 for file in files: if not file.is_directory(): result = self.count(urllib.unquote(file.get_uri()[7:])) lines += result[0] chars += result[1] self.property_label = gtk.Label('Linecount') self.property_label.show() self.hbox = gtk.HBox(0, False) self.hbox.show() label = gtk.Label('Lines:') label.show() self.hbox.pack_start(label) self.value_label = gtk.Label() self.hbox.pack_start(self.value_label) self.value_label.set_text(str(lines)) self.value_label.show() self.chars_label = gtk.Label('Characters:') self.chars_label.show() self.hbox.pack_start(self.chars_label) self.chars_value = gtk.Label() self.hbox.pack_start(self.chars_value) self.chars_value.set_text(str(chars)) self.chars_value.show() return nautilus.PropertyPage("NautilusPython::linecount", self.property_label, self.hbox),
圖 3 展示了在文件上單擊右鍵并單擊 Linecount 選項(xiàng)卡的結(jié)果。此時(shí),需要注意,這一特性可用于文件或者任何一組選定的文件和目錄。所報(bào)告的數(shù)字將代表所有文件中的所有行。
圖 3. 單擊 Linecount 選項(xiàng)卡來(lái)查看文件的行數(shù)
最后,修改擴(kuò)展函數(shù)來(lái)填充一列而不是整個(gè)屬性頁(yè)。因而代碼的修改相當(dāng)少,盡管需要同時(shí)從 nautilus.ColumnProvider 和 nautilus.InfoProvider 繼承。還必須執(zhí)行 get_columns 和 update_file_info。方法 get_columns 僅返回由方法 count 獲取的信息。
方法 count 為列提供程序擴(kuò)展采用不同的技術(shù)。Python 的 readlines 例程用于將一個(gè)文件的所有行讀取到一列字符串中。計(jì)算行的總數(shù)就是在 len(s) 語(yǔ)句中返回的清單元素的數(shù)量。在兩個(gè)例子中都要進(jìn)行文件類(lèi)型檢查:這是要確保僅對(duì)包含需要計(jì)數(shù)行的文本文件進(jìn)行計(jì)數(shù)。可利用如下行來(lái)創(chuàng)建一列可接受的文件擴(kuò)展:
types = ['.py','.js','.html','.css','.txt','.rst','.cgi']
第二個(gè)清單包含了不會(huì)被計(jì)數(shù)的異常,對(duì)于本例來(lái)說(shuō),包含具有如下行的文件:
exceptions = ['MochiKit.js']
這兩個(gè)清單用于包括或者排除具有如下兩行代碼的文件:
if ext not in types or basename in exceptions: return 0
整個(gè)擴(kuò)展需要 26 行可執(zhí)行代碼。您可能想要修改擴(kuò)展,并輸入清單來(lái)包含或者排除感興趣的文件,清單 4 展示了完整的擴(kuò)展。
清單 4. 用于 Linecountcolumn 擴(kuò)展的 Python 代碼
import nautilus import urllib import os types = ['.py','.js','.html','.css','.txt','.rst','.cgi'] exceptions = ['MochiKit.js'] class LineCountExtension(nautilus.ColumnProvider, nautilus.InfoProvider): def __init__(self): pass def count(self, filename): ext = os.path.splitext(filename)[1] basename = os.path.basename(filename) if ext not in types or basename in exceptions: return 0 s = open(filename).readlines() return len(s) def get_columns(self): return nautilus.Column("NautilusPython::linecount", "linecount", "Line Count", "The number of lines of code"), def update_file_info(self, file): if file.is_directory(): lines = 'n/a' else: lines = self.count(urllib.unquote(file.get_uri()[7:])) file.add_string_attribute('linecount', str(lines))
圖 4 顯示了啟用 Line Count 列的 Nautilus 窗口。每個(gè)單獨(dú)的文件顯示全部行數(shù)。您需要利用該方法進(jìn)行一次計(jì)算就可以知道您總共需要多少個(gè)文件。
圖 4. Nautilus 窗口中的 Line Count 列
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“怎么用Python擴(kuò)展和延伸Nautilus”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。