只运行一个Python程序(如Firefox)?
当我打开Firefox浏览器,然后运行这个命令:
firefox http://somewebsite
这个网址就会在Firefox的新标签页中打开(在Chromium浏览器中也是一样的情况)。有没有什么方法可以在Python中实现这种行为呢?比如,调用:
processStuff.py file/url
然后再调用:
processStuff.py anotherfile
这样就不应该启动两个不同的进程,而是发送一个消息给当前正在运行的程序。例如,你可以在一个带标签的对话框中显示信息,而不是打开10个单独的窗口。
如果有人能描述Firefox/Chromium是如何做到这一点的,并且能够跨平台使用,我会加赏金。
5 个回答
虽然我不确定Firefox或Chrome是否是这样做的,但其实你可以不使用套接字,仅依靠文件系统来实现你的目标。我发现很难用文字表达,所以下面有一个粗略的流程图,展示了可以如何做到这一点。我觉得这种方法有点像使用cookie :)。最后再提一句,使用这种方法可以在多个会话之间存储工作区或标签页。
编辑
根据一个评论,环境变量在不同的进程之间是不能共享的。我到目前为止的所有工作都是在一个进程中调用多个模块。抱歉让你感到困惑。
你可以创建一个数据目录,在你的程序运行时,先检查一下有没有一个“锁定文件”。如果没有,就创建这个文件。
如果这个文件已经存在,那你就需要尝试和已经在运行的程序进行沟通。可以通过创建一个套接字、管道或者类似的东西来实现,然后把它的地址或者路径以合适的方式传递给你。
具体的实现方法有很多,取决于你的程序运行在哪个平台上。
Firefox的工作方式是这样的:第一次启动时,它会创建一个叫做socket文件(在Windows上是命名管道)。这个文件的作用是让后续的Firefox实例能够发现并与第一个实例进行沟通,并在关闭之前把网址转发给它。因为socket文件或命名管道只能被本地系统上的进程访问(就像普通文件一样),所以网络上的客户端无法访问它。而且因为它们是文件,防火墙也不会阻止它们(就像在文件上写东西一样)。
下面是一个简单的实现来说明我的意思。在第一次启动时,会创建一个叫做lock.sock
的socket文件。之后再次启动这个脚本时,会检测到这个锁,并把网址发送给它:
import socket
import os
SOCKET_FILENAME = 'lock.sock'
def server():
print 'I\'m the server, creating the socket'
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.bind(SOCKET_FILENAME)
try:
while True:
print 'Got a URL: %s' % s.recv(65536)
except KeyboardInterrupt, exc:
print 'Quitting, removing the socket file'
s.close
os.remove(SOCKET_FILENAME)
def client():
print 'I\'m the client, opening the socket'
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.connect(SOCKET_FILENAME)
s.send('http://stackoverflow.com')
s.close()
def main():
if os.path.exists(SOCKET_FILENAME):
try:
client()
except (socket.error):
print "Bad socket file, program closed unexpectedly?"
os.remove(SOCKET_FILENAME)
server()
else:
server()
main()
你应该实现一个合适的协议(比如发送正确的数据包,而不是硬编码长度),可以考虑使用SocketServer,但这超出了这个问题的范围。Python Socket编程指南也可能对你有帮助。我没有Windows机器,所以无法确认它在那个平台上是否有效。