Как вызвать метод из уже запущенного сценария python

88
8

Мне нужно проверить, запущен ли скрипт 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')

спросил(а) 2021-01-25T15:18:53+03:00 4 месяца, 3 недели назад
1
Решение
63

Сокеты являются хорошим решением этой проблемы межпроцессного взаимодействия.

Одним из возможных подходов было бы создание сервера сокетов в потоке в исходном процессе, который может использоваться в качестве точки входа для внешнего ввода. Пример (довольно глупый) может быть:

# 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

Это отнюдь не единственное решение вашей проблемы, но оно, вероятно, будет одним из самых простых.

ответил(а) 2021-01-25T15:18:53+03:00 4 месяца, 3 недели назад
63

Вам либо нужно:

    Проактивная проверка вашего рабочего процесса для просмотра среды (например, содержимого файла или данных, поступающих через сокет), чтобы знать, когда следует запускать функцию, или для выполнения вашего процесса получения сигналов unix или другого IPC (возможно, одного из определяемых пользователем сигналов) и выполнения функции при получении.

В любом случае вы не можете просто перейти к запущенному процессу и запустить функцию внутри этого процесса (это НЕ МОЖЕТ быть невозможен, если вы перехватите запущенный процесс до отладчика, но я бы не рекомендовал его).

Tkinter обязательно есть своя система событий, поэтому я рекомендую прочитать, как это работает, и как либо запускать что-либо по таймеру в этой системе циклов событий, либо настроить обратный вызов, реагирующий на сигнал. Вы также можете обернуть систему, основанную на отсутствии события, в блоке try/except, который поймает исключение, генерируемое сигналом UNIX, но может быть нелегко возобновить работу остальной части программы после того, как этот сигнал поймается, в таком случае.

ответил(а) 2021-01-25T15:18:53+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема