Nautilus脚本踩坑记录:为Gnome文件浏览器(Nautilus)添加右键菜单,快速打开Tensorboard

引子

当使用Tensorboard进行神经网络训练的可视化时,训练完后可能有许多记录文件夹,在shell里使用命令查看各个训练结果十分不便(需要指定具体的文件夹),因此有了在文件浏览器中添加右键菜单,快速打开Tensorboard查看记录的想法。

Nautilus脚本

由于自己使用的是Ubuntu自带的Gnome桌面,而Nautilus又原生提供自定义脚本的功能,因此参考[1]即可实现脚本的添加,需要注意的是~/. local /share/nautilus/scripts中的脚本需要设置为可执行才能被添加到右键菜单中。

使用右键快速打开Tensorboard

这是是我遇到的坑最多的地方,现在功能实现后再回过头反思,觉得问题主要出在一开始需求定义的时候把简单的需求复杂化了。
其实一开始只是觉得在shell里输入tensorboard的启动命令太麻烦了(需要指定具体的文件夹),所以想在右键菜单里加一个命令,可以直接在shell中启动tensorboard命令,并指定logdir为当前选择的文件夹。实现该功能最简单的方法就是使用shell脚本。

方案一(python脚本)

但是一开始我的想法是不显示shell界面,而是用python脚本在后台执行tensorboard命令,并且实时获取tensorboard命令的输出,当得到tensorboard输出的url时,利用PyGObject模块显示一个对话窗口,点击该对话窗口中的按键即可打开浏览器查看可视化结果。但是在这其中遇到了许多坑,最终也没有实现,这里把遇到的坑做一个记录。

  1. Nautilus脚本需要在文件首先声明解释器,否则脚本无法正常运行,例如:
shell的解释器:
#!/bin/bash
python的解释器:
#!/usr/bin/env python
  1. python 3.8.5 使用pip安装PyGObject时报错ERROR: Could not build wheels for PyGObject which use PEP 517 and cannot be installed directly以及undefined symbol: cairo_svg_surface_set_document_unit
    解决方法是:
    · 首先使用pip安装1.11.1版本的pycairo:pip3 install pycairo==1.11.1
    · 然后使用命令python -m pip install --no-use-pep517 PyGObject进行安装。
  2. 如下的测试代码是为了实时获取tensorflow的输出,并且从输出中提取出类似http://localhost:6006/的url,在这里遇到的一个坑是tensorboard的输出是以stderr的方法打印的,而不是通常的stdout,这一点可以参考代码注释。
#!/usr/bin/env python
import os
from subprocess import Popen, PIPE
import re 
  
def Find(string):   
    # findall() has been used  
    # with valid conditions for urls in string 
    regex = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))"
    url = re.findall(regex,string)       
    return [x[0] for x in url] 
    
def run(command):
    # 这里一定要注意是stderr,否则无法获取到tensorboard的打印输出
    sub=Popen(command, stderr=PIPE, shell=True)
    while True:
        line = sub.stderr.readline().rstrip().decode('utf8')
        if not line:
            break
        yield line
        
if __name__ == "__main__":
    selected = os.environ.get('NAUTILUS_SCRIPT_SELECTED_FILE_PATHS', '')
    command = "tensorboard "+"--logdir "+selected

    for path in run(command):
        url=Find(path)
        if url:
            break
  1. 上面的测试代码在命令行中运行起来表现符合预期,但是如果通过右键菜单运行,则无法启动tensorboard,也是因为这个原因,所以这条路没有走下去。如果有大佬知道解决方案,还请留言赐教。

方案二(shell脚本)

方案二就是改用shell脚本,而非python脚本,这种方案虽然视觉效果可能没有方案一好,但是却是最直接,最快速的实现,最终脚本如下:

#!/bin/bash
for url in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS 
do
cmd="source /home/wangpeng/anaconda3/bin/activate; conda activate base; tensorboard --logdir $url ; bash"
gnome-terminal -- bash -c "$cmd ;read"
done

在实现的过程中,同样遇到了一些坑,记录一下:

  1. shell中的环境变量在声明时变量名以及变量值与=之间不能有空格,另外[2]比较详细地介绍了shelll中字符串的声明方法及需要注意的项。
下面这样可以正确赋值:
cmd="abc"
但是这样就无法正确赋值:
cmd = "abc"
  1. 根据[3],Nautilus脚本中可以获取4种与当前右键菜单有关的环境变量:
    NAUTILUS_SCRIPT_SELECTED_FILE_PATHS就是我们需要的环境变量,本来以为该变量是以数组形式存储的,所以想通过${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS[0]}来获取每个值[4],然而实际上并不能通过这种方式来枚举,这里如果如果有大佬知道解决方案,还请留言赐教。
    所以最终参考[3],通过for xx in xx的方式来获取各个值。
NAUTILUS_SCRIPT_SELECTED_FILE_PATHS:用新行分开的所选文件的路径(除非是本地文件) # 是当前选择的文件(夹)的路径
NAUTILUS_SCRIPT_SELECTED_URIS:用新行分开的所选文件的 URI # 是当前选择的文件(夹)的URI(即带有file:\\前缀)
NAUTILUS_SCRIPT_CURRENT_URI:当前位置的 URI # 是当前选择的文件(夹)的URI(即带有file:\\前缀)
NAUTILUS_SCRIPT_WINDOW_GEOMETRY:当前窗口的位置和大小

总结

解决方案不止一种,时间紧张的情况下,优先考虑最快速的方案,不要太纠结于形式。

参考

[1]ubuntu14.04右键菜单添加sublime打开选项
[2]shell脚本系列:shell脚本中的字符串
[3]Linux nautilus 右键菜单脚本
[4]linux的shell数组变量,给环境变量赋多个值

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值