如何强制旧版本的eog在新实例中运行?

2 投票
2 回答
595 浏览
提问于 2025-04-17 02:33

我有一个小的Python脚本,用来显示图片。这个脚本的做法是先把图片写到一个临时文件里,然后用一个叫eog的程序打开这个临时文件,最后在eog程序关闭后再删除这个临时文件。相关的代码大致是这样的:

os.popen('(eog --new-instance tmp.jpg; rm tmp.jpg)&')

这里的--new-instance这个选项很重要;如果没有这个选项的话,如果已经有一个eog程序在运行,新的eog调用就会直接告诉那个已经在运行的程序去显示tmp.jpg,然后立刻返回。这样一来,rm命令就会在那个正在运行的eog程序打开tmp.jpg之前执行,导致那个程序崩溃。

不幸的是,我对一些使用这个脚本的系统没有完全的控制权。有些系统上安装的eog版本比较旧,不支持--new-instance选项,而我又不想浪费我的存储空间去构建一个本地版本。

有没有办法让我启动eog时不让它检测到其他的实例?或者有没有其他可靠的方法可以在一个功能更强大的查看器中显示图片(比如支持缩放、平移等功能),而不会在我的目录里留下临时文件呢?

2 个回答

0

eog 是一个查看图片的程序,它会根据文件名来监控文件,所以你不能直接打开一张图片后就安全地删除它。

你可以在删除文件之前先设置一个延迟:

#!/usr/bin/env python
import os
import subprocess
import tempfile
import time

from threading import Thread

def write_image_to(f):
    f.write(open(os.path.expanduser('~/Pictures/lenaNN.jpg'), 'rb').read())

def f(write_image_to, delay=None):
    with tempfile.NamedTemporaryFile() as fileobj:
        write_image_to(fileobj)
        fileobj.flush() # ensure writing to disk

        r = subprocess.call(['eog','--new-instance',fileobj.name],close_fds=True)
        if r: # eog don't support new-instance
           subprocess.call(['eog', fileobj.name], close_fds=True)
           if delay:
              time.sleep(delay)

for _ in xrange(10): 
    Thread(target=f, args=(write_image_to, 3600)).start()

为了避免等待这个延迟结束,你可以把脚本放在后台运行:

$ python your_script.py & disown

disown 可以确保即使你退出登录,脚本也能继续运行。

0

可能有更好的方法来完成这个任务,但如果你想确保在 eog 完成之前不运行 rm,你可以在 Popen 对象上使用 wait()。这样可以解决你的崩溃问题,但你还需要检查是否有正在运行的 eog 进程。

import subprocess as subp
import os, signal
findInstance = subp.check_output('ps -eaf | grep eog', shell=True).strip()
for line in findInstance.decode('utf-8').split('\n'):
    if line.split()[7] == 'eog':
        os.kill(int(line.split()[1]), signal.SIGKILL)
subp.Popen(['eog','tmp.jpg']).wait()
subp.Popen(['rm','tmp.jpg'])

这段代码会查找 eog 进程,如果找到了,就会把它结束掉。然后,它会重新启动 eog,这样就可以显示新的图片,并在 eog 完成后再删除临时图片。

撰写回答