怎么用Python扩展和延伸Nautilus

88次阅读
没有评论

共计 8635 个字符,预计需要花费 22 分钟才能阅读完成。

这篇文章主要介绍了怎么用 Python 扩展和延伸 Nautilus,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让丸趣 TV 小编带着大家一起了解一下。

Nautilus 脚本

扩展 Nautilus 的第一个方法是通过在 /home 中发现的名为 .gnome2/nautilus-scripts 的特定目录。当在 Scripts   菜单下的文件或者文件夹上点击鼠标右键时,该目录下所有可执行文件将会出现。还可以选择多个文件或者文件夹,并采用相同的右击方法,将文件清单传递给脚本。

当调用脚本时,Nautilus 支持多个包含当前目录以及所选文件等内容的环境变量。表 1 展示了这些环境变量。

表 1. Nautilus 环境变量

环境变量描述 NAUTILUS_SCRIPT_SELECTED_FILE_PATHS 所选文件的新行分割路径(仅针对本地)NAUTILUS_SCRIPT_SELECTED_URIS 所选文件的新行分割 URIsNAUTILUS_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):
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):
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 列

感谢你能够认真阅读完这篇文章,希望丸趣 TV 小编分享的“怎么用 Python 扩展和延伸 Nautilus”这篇文章对大家有帮助,同时也希望大家多多支持丸趣 TV,关注丸趣 TV 行业资讯频道,更多相关知识等着你来学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计8635字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)