#python #python-3.x
Вопрос:
Моя задача заключается в следующем:
- Нажмите F на клавиатуре
- Выполнить функцию в другом скрипте
- Снова нажмите F на клавиатуре и остановите выполнение сценария, который я только что запустил.
- Может быть, снова нажать F и начать все сначала.
Чтобы упростить задачу, я написал функцию PrintNumbers.py. Я не хочу впадать в бесконечный цикл, поэтому я останавливаю функцию, досчитав до 10. На самом деле я хочу, чтобы мой код выполнялся вечно, пока я не скажу ему остановиться.
import time
global stopnow
stopnow = False
def stopPrinting():
global stopnow
stopnow = True
def PrintNumbers():
global stopnow
x = 0
while (x < 10) and not stopnow:
x = x 1
#if x == 5:
# stopPrinting()
print('X is: %sStopnow is %s' % (x, stopnow))
time.sleep(1)
if __name__ == "__main__":
PrintNumbers()
Теперь я пытаюсь вызвать его из другого файла, main.py:
import keyboard
import time
import PrintNumbers as pN
IsPressed = False
# once you press the button('f') the function happens once
# # when you release the button('f') the loop resets
while True:
if not keyboard.is_pressed('f'):
IsPressed = False
pN.stopnow
while not IsPressed:
if keyboard.is_pressed('f'):
print('pN now counting to 10!')
IsPressed = True
pN.PrintNumbers()
Итак, я понимаю, я «увольняю и забываю» свои номера pN.Printnumbers, но я не могу найти ни одного примера в WWW, как решить эту проблему.
Я даже трачу часы на TkInter, чтобы заставить эту работу работать с помощью кнопок запуска и остановки, только чтобы понять, что мой основной цикл зависает во время выполнения. Даже нарезание резьбы не работает, и я начинаю расстраиваться.
Очень рассчитываю на вашу поддержку.
PS: Я хотел бы увидеть и по-настоящему оценить решения для копирования и вставки, чтобы я мог попробовать их сам и понять, что вы, эксперты, предлагаете.
С уважением, Криссо!
Комментарии:
1. Было бы более полезно показать ваши попытки с помощью Tkinter и/или потоков; использование чего-то подобного необходимо , поэтому полезного ответа на этот вопрос в написанном виде не будет.
Ответ №1:
Существует несколько способов взаимодействия с функцией, как вы описали. Выполнение этого с помощью Tkinter добавляет уровень сложности, потому что вам приходится иметь дело с потоком графического интерфейса, но это не так уж плохо. Я покажу пример в tkinter, используя привязку:
from tkinter import *
class App(Tk): #Main window
def __init__(self):
Tk.__init__(self)
self.output = False
self.num = 0
self.text = Text(self)
self.text.pack()
self.bind('<f>', self.OnKeyPress) #The bind creates a link between pressing f and "App.OnKeyPress"
self.NumberOutput()
def NumberOutput(self):
if self.output:
self.text.insert('end', str(self.num))
self.num = 1
self.after(1000, self.NumberOutput) #using after(ms, function) keeps the GUI from locking
def OnKeyPress(self, event):
self.output = not self.output
self.num = 0
if __name__ == '__main__':
app = App()
app.mainloop()
Я оставлю это в качестве упражнения, чтобы переместить числовые данные в свой собственный файл сценария.
Примечание: Вы можете использовать привязку для привязки к любой функции, а не только к чему-то определенному в приложении.
Комментарии:
1. Привет, Джаред, очень признателен, большое тебе спасибо. Ваш код очень и очень сложен для меня, как для новичка, мне потребуется некоторое время, чтобы понять это. self.after-это то, о чем я слышал, но еще не понял, почему это необходимо.
self.output = not self.output
Для чего используется?2. Привет, Джаред, твой код работает нормально — однако, я думаю, это не совсем то, что я ищу. Поэтому я изменил
def NumberOutput(self): if self.output: pN.PrintNumbers()
, когда я нажимаю f, чтобы остановить выполнение, весь pN.printNumbers выполняет полную итерацию и останавливается после этого. Но я хочу, чтобы pN.printNumbers добавлял числа до бесконечности и приказывал ему остановиться, когда я прикажу…3. @ChrIsso Если вы вызовете функцию внутри tkinter, графический интерфейс перестанет выполняться до тех пор, пока эта функция не будет завершена. Это означает, что вам нужно либо заставить поток графического интерфейса вызывать генератор чисел один раз в секунду, используя что-то вроде self.after(1000, self. CallNumberOutput), или вам нужно запустить генератор чисел в отдельном потоке. Это ограничение способа написания tkinter, поскольку он взаимодействует с кодом на языке Си. Если вы идете по маршруту потока, вам нужен объект синхронизации для отправки команды включения/выключения в поток генерации чисел. Я бы предложил очередь (очередь модулей. Очередь)
Ответ №2:
мой код слишком длинный для комментария, поэтому я публикую это в качестве ответа.
Вот моя попытка с Tkinter и процессом.
from tkinter import *
import time
import PrintNumbers as pN
from multiprocessing import Process, Queue
#################
# Main Functions
#################
def clickedStart():
#pN.PrintNumbers()
myProcess1 = Process(target=pN.PrintNumbers(), args=())
myProcess1.start()
print(f'Process1 is alive: {myProcess1.is_alive()}')
myProcess1.kill()
time.sleep(1)
print(f'Process1 is still alive: {myProcess1.is_alive()}')
#################
# TK Inter Design
#################
window = Tk()
window.title("Start/Stop Counting")
#window.geometry('350x200')
startbtn = Button(window, text="Start",command=lambda: clickedStart())
startbtn.grid(column=1, padx=20,pady=20,row=0)
stopbtn = Button(window, text="Stop")
stopbtn.grid(column=3, padx=20,row=0)
global queue
queue = Queue()
window.mainloop()
Однако мои окна Tkinter полностью зависают до тех пор, пока процесс не будет завершен.
Я не могу переместить окно, я не могу нажать «Стоп» — ничего.