我需要检查python脚本是否已经在运行,然后从同一个运行的python脚本调用一个方法。但它必须在同一个过程(pid)上,没有新的过程。这可能吗?
我尝试了一些代码但没有工作。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Tkinter as tk
from Tkinter import *
import socket
class Main():
def mainFunc(self):
self.root = tk.Tk()
self.root.title("Main Window")
self.lbl = Label(self.root, text = "First Text")
self.lbl.pack()
openStngs = Button(self.root, text = "Open Settings", command=self.settingsFunc)
openStngs.pack()
def settingsFunc(self):
stngsRoot = Toplevel()
stngsRoot.title("Settings Window")
changeTextOfLabel = Button(stngsRoot, text = "Change Main Window Text", command=self.change_text)
changeTextOfLabel.pack()
def change_text(self):
self.lbl.config(text="Text changed")
# the get_lock from http://stackoverflow.com/a/7758075/3254912
def get_lock(process_name):
lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
try:
print lock_socket
lock_socket.bind('\0' + process_name)
print 'I got the lock'
m.mainFunc()
mainloop()
except socket.error:
print 'lock exists'
m.settingsFunc()
mainloop()
# sys.exit()
if __name__ == '__main__':
m=Main()
get_lock('myPython.py')
答案 0 :(得分:2)
套接字是解决这种进程间通信问题的好方法。
一种可能的方法是在原始进程的线程中设置套接字服务器,这可以用作外部输入的入口点。一个(相当愚蠢的)例子可能是:
# main.py
import socket
import SocketServer # socketserver in Python 3+
import time
from Queue import Queue
from threading import Thread
# class for handling requests
class QueueHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
self.server = server
server.client_address = client_address
SocketServer.BaseRequestHandler.__init__(self,request, client_address, server)
# receive a block of data
# put it in a Queue instance
# send back the block of data (redundant)
def handle(self):
data = self.request.recv(4096)
self.server.recv_q.put(data)
self.request.send(data)
class TCPServer(SocketServer.TCPServer):
def __init__(self, ip, port, handler_class=QueueHandler):
SocketServer.TCPServer.__init__(self, (ip, port), handler_class, bind_and_activate=False)
self.recv_q = Queue() # a Queue for data received over the socket
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_bind()
self.server_activate()
def shutdown(self):
SocketServer.TCPServer.shutdown(self)
def __del__(self):
self.server_close()
# This is the equivalent of the main body of your original code
class TheClassThatLovesToAdd(object):
def __init__(self):
self.value = 1
# create and instance of the server attached to some port
self.server = TCPServer("localhost",9999)
# start it listening in a separate control thread
self.server_thread = Thread(target=self.server.serve_forever)
self.server_thread.start()
self.stop = False
def add_one_to_value(self):
self.value += 1
def run(self):
while not self.stop:
print "Value =",self.value
# if there is stuff in the queue...
while not self.server.recv_q.empty():
# read and parse the message from the queue
msg = self.server.recv_q.get()
# perform some action based on the message
if msg == "add":
self.add_one_to_value()
elif msg == "shutdown":
self.server.shutdown()
self.stop = True
time.sleep(1)
if __name__ == "__main__":
x = TheClassThatLovesToAdd()
x.run()
当你开始这个跑步时,它应该只是循环打印到屏幕上。输出:
Value = 1
Value = 1
Value = 1
...
然而,附加到TCPServer
实例的TheClassThatLovesToAdd
实例现在为我们提供了一个控制路径。最简单的控制代码片段是:
# control.py
import socket
import sys
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.settimeout(2)
sock.connect(('localhost',9999))
# send some command line argument through the socket
sock.send(sys.argv[1])
sock.close()
因此,如果我在一个终端窗口中运行main.py
并从另一个终端窗口调用python control.py add
,则main.py
的输出将会更改:
Value = 1
Value = 1
Value = 1
Value = 2
Value = 2
...
最后要杀死它,我们可以运行python control.py shutdown
,这会轻轻地让main.py
停止。
这绝不是解决问题的唯一方法,但它可能是最简单的解决方案之一。
答案 1 :(得分:1)
您需要:
无论哪种方式,你都不能只是进入一个正在运行的进程并在该进程中触发一个函数(如果你将正在运行的进程挂钩到一个调试器,那么可能不可能完全不可能,但我不推荐它。) / p>
Tkinter
必然有自己的事件循环系统,所以我建议阅读它是如何工作的,以及如何在该事件循环系统中的定时器上运行某些东西,或者设置一个响应信号的回调。您还可以将一个基于非事件循环的系统包装在try / except块中,该块将捕获由UNIX信号生成的异常,但是在捕获到该信号之后恢复程序其余部分的操作可能并不简单,在那种情况下。
答案 2 :(得分:0)
可以尝试GDB,但不确定如何从[空闲线程]内调用函数。
也许某人非常熟悉gdb并从GDB中调试/调用Python函数可以改善此答案。