溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么用Python擴(kuò)展和延伸Nautilus

發(fā)布時(shí)間:2021-10-27 16:34:49 來(lái)源:億速云 閱讀:206 作者:小新 欄目:系統(tǒng)運(yùn)維

這篇文章主要介紹了怎么用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í)行該腳本。

怎么用Python擴(kuò)展和延伸Nautilus

圖 1.在 Nautilus 中選擇文件

圖 2 展示了 Filecount.py 腳本的運(yùn)行結(jié)果。

怎么用Python擴(kuò)展和延伸Nautilus

圖 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ù)字將代表所有文件中的所有行。

怎么用Python擴(kuò)展和延伸Nautilus

圖 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è)文件。

怎么用Python擴(kuò)展和延伸Nautilus

圖 4. Nautilus 窗口中的 Line Count 列

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“怎么用Python擴(kuò)展和延伸Nautilus”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI