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