我正在尝试使用Python编写的OS X应用程序,并且需要检测是否已经存在使用某些脚本运行的Python.app实例。该脚本从CFBundleName
到Python
即时修改MyApp
以更改菜单栏中的应用标题。
bundle = NSBundle.mainBundle()
info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
info['CFBundleName'] = 'MyApp'
如果我启动另一个实例并检查正在运行的应用的CFBundleName
,它只会告诉我原始值,即Python
:
for app in NSWorkspace.sharedWorkspace().runningApplications():
bundle = NSBundle.bundleWithURL_(app.bundleURL())
info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
name = info.get('CFBundleName')
if name in ('Python', 'MyApp'):
print name # => prints Python
所以我需要找到一种方法来标记运行MyApp脚本的Python.app实例,以便能够中止启动重复实例。
有这样的方法吗?
更新
在有更好的解决方案之前,我将使用lockf
import fcntl
lockfile = open('/tmp/myapp.lock', 'w')
fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
更新2:
好吧,我仍然需要找到我关注的应用程序。目前,我只是循环遍历所有Python.app实例并逐个关注它们。通常,只有一个,但如果它们很少,它可能会很混乱。
from Foundation import NSWorkspace
from Cocoa import NSApplicationActivateAllWindows, NSApplicationActivateIgnoringOtherApps
try:
import fcntl
lockfile = open('/tmp/myapp.lock', 'w')
fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError as e:
assert (e.errno, e.strerror) == (35, 'Resource temporarily unavailable')
for app in NSWorkspace.sharedWorkspace().runningApplications():
if app.bundleIdentifier() == 'org.python.python':
app.activateWithOptions_(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)
exit()
更新3:
我将使用pid文件,直到出现更好的解决方案
LOCK_FILE = '/tmp/myapp.lock'
PID_FILE = '/tmp/myapp.pid'
try:
import fcntl
# NOTE: needs to be assigned to a variable for the lock to be preserved
lockfile = open(LOCK_FILE, 'w')
fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError as e:
try:
with open(PID_FILE) as f:
pid = int(f.read())
except:
pid = None
for app in NSWorkspace.sharedWorkspace().runningApplications():
if app.bundleIdentifier() == 'org.python.python':
if not pid or pid == app.processIdentifier():
app.activateWithOptions_(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)
exit()
from Foundation import NSProcessInfo
info = NSProcessInfo.processInfo()
pid = info.processIdentifier()
with open(PID_FILE, 'w+') as f:
f.write(str(pid))