只运行一个Python程序(如Firefox)?

14 投票
5 回答
1006 浏览
提问于 2025-04-16 23:11

当我打开Firefox浏览器,然后运行这个命令:

firefox http://somewebsite

这个网址就会在Firefox的新标签页中打开(在Chromium浏览器中也是一样的情况)。有没有什么方法可以在Python中实现这种行为呢?比如,调用:

processStuff.py file/url

然后再调用:

processStuff.py anotherfile

这样就不应该启动两个不同的进程,而是发送一个消息给当前正在运行的程序。例如,你可以在一个带标签的对话框中显示信息,而不是打开10个单独的窗口。

如果有人能描述Firefox/Chromium是如何做到这一点的,并且能够跨平台使用,我会加赏金。

5 个回答

2

虽然我不确定Firefox或Chrome是否是这样做的,但其实你可以不使用套接字,仅依靠文件系统来实现你的目标。我发现很难用文字表达,所以下面有一个粗略的流程图,展示了可以如何做到这一点。我觉得这种方法有点像使用cookie :)。最后再提一句,使用这种方法可以在多个会话之间存储工作区或标签页。

编辑
根据一个评论,环境变量在不同的进程之间是不能共享的。我到目前为止的所有工作都是在一个进程中调用多个模块。抱歉让你感到困惑。

文件系统消息中继

8

你可以创建一个数据目录,在你的程序运行时,先检查一下有没有一个“锁定文件”。如果没有,就创建这个文件。

如果这个文件已经存在,那你就需要尝试和已经在运行的程序进行沟通。可以通过创建一个套接字、管道或者类似的东西来实现,然后把它的地址或者路径以合适的方式传递给你。

具体的实现方法有很多,取决于你的程序运行在哪个平台上。

24

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机器,所以无法确认它在那个平台上是否有效。

撰写回答