#python #kivy
#python #kivy
Вопрос:
Я обращаюсь к вам, сообщество, поскольку я исчерпал все идеи о том, как заставить это работать.
В основном в одном методе я проверяю паспорт с помощью камеры и извлекаю определенные функции.
Мне нужен метод send_data_to_the_server()
, который будет ждать, пока первая функция check_passport()
не даст мне ожидаемый результат. Когда результат получен и есть True
, следующая функция (которая подключается к серверу) может продолжаться.
Я пытался заставить ее работать time.sleep()
, что оказалось очень неэффективным, поскольку она замораживает всю программу и перестает отвечать на запросы, и я должен ее убить.
Затем я попытался использовать queue.Queue
с threading
модулями. Это тоже зависает.
мой код:
def check_passport(self, id, q): # <-- this function needs to finish and return True
self.validate_passport = NewUserValidationCamera()
self.root.add_widget(self.validate_passport)
if self.validate_passport._passport_passed: # this private variable will become True at some point
q.put((id, 'finished'))
# while not self.validate_passport._passport_passed:
# time.sleep(0.5)
# return True
def send_data_to_the_server(self): # this method waits until method "check_passport" returns True
...
...
def register_or_login(self):
if self.login_screen is False:
passport_passed = False
q = queue.Queue()
thread1 = threading.Thread(target=self.check_passport, args=(1, q))
thread2 = threading.Thread(target=self.send_data_to_the_server)
for thread in [thread1, thread2]:
thread.daemon = True
thread.start()
result = q.get()
print(result)
Как я уже сказал, мое решение независимо от того, использую я time
приложение или threading
зависает. Я также использовал while not self.validate_passport._passport_passed: time.sleep(0.5)
, но приложение также перестает отвечать на запросы.
Что вам, вероятно, также нужно знать, так это то, что self.validate_passport = NewUserValidationCamera()
запускается весь процесс проверки, потому что он запускается в __init__()
методе.
Обновленный код, отражающий добавленную очередь для второго метода:
def register_or_login(self):
if self.login_screen is False:
passport_passed = False
q1 = queue.Queue()
q2 = queue.Queue()
thread1 = threading.Thread(target=self.create_a_validation_widget_and_check_passport, args=(1, q1))
thread2 = threading.Thread(target=self.send_data_to_the_server, args=(2, q2))
for thread in [thread1, thread2]:
thread.daemon = True
thread.start()
thread.join()
result1 = q1.get()
result2 = q2.get()
print(result1)
Любая помощь очень ценится.
Комментарии:
1. Вы пробовали thread.join()?
2. Нет, я этого не делал. Попробую ..
3. Я не уверен во всей архитектуре приложения, но похоже, что вам нужен флаг файла в системе, если указанный файл существует, show может продолжаться
4. Хорошо, возможно, я здесь неправильно понимаю. Но разве метод password не может просто вызвать метод отправки данных, когда он будет готов?
5. Я еще не понял, в чем суть вопроса. Я не думаю, что это имеет какое-либо отношение к коду потока. Все это кажется простым и правильным.
create_a_validation_widget_and_check_passport1
должен выполняться, и если он возвращается нормально,send_data_to_the_server
затем должен выполняться. Я просто разделил ваш код на две простые функции, и это сработало как для того, чтобы просто использоватьjoin()
то, что вы делаете здесь, так и для того, чтобы отключить оба потока одновременно и заставить один ждать изменения глобальной переменной другим, прежде чем он сделает свое дело.
Ответ №1:
Я думаю, вы можете использовать очередь и поток.объединяйтесь вот так
def __init__(self):
self.que = queue.Queue() # will use for get the data from the check_passport
self.thread1 = None # will use this attribute in send_data method to wait the check_passport
self.register_or_login()
def check_passport(self, id, q):
self.validate_passport = NewUserValidationCamera()
self.root.add_widget(self.validate_passport)
if self.validate_passport._passport_passed:
q.put((id, 'finished'))
return True
def send_data_to_the_server(self):
self.thread1.join() # The method waits for the thread1
print("check_passport: ", self.que.get())
...
def register_or_login(self):
if self.login_screen is False:
passport_passed = False
self.thread1 = threading.Thread(target=lamda id, q: self.que.put(self.check_passport(id, q)), args=(1, q))
# the lambda function puts the result of the check_passport in the self.que
thread2 = threading.Thread(target=self.send_data_to_the_server)
for thread in [self.thread1, thread2]:
thread.daemon = True
thread.start()
result = q.get()
print(result)
Редактировать:
Прежде чем ответить на вопрос, я написал небольшой пример, и я хотел бы поделиться примером, чтобы вы могли протестировать код.
class test:
def __init__(self):
self.que = queue.Queue()
self.thread1 = threading.Thread(target=lambda arg1, arg2: self.que.put(self.func_1(arg1, arg2)), args=["hello", "world"])
self.thread1.start()
thread2 = threading.Thread(target=self.func_2)
thread2.start()
def func_1(self, foo_1, foo_2):
for bar in range(10):
print(bar)
time.sleep(1)
return "{} {}".format(foo_1, foo_2)
def func_2(self):
self.thread1.join()
result = self.que.get()
print(result)
Комментарии:
1. Вы действительно запустили этот код и увидели, что он работает? Я не нахожусь в критическом состоянии, и я не знаю, должно ли это работать или не должно. Вот почему я спрашиваю. Мне просто любопытно.
2. Не этот код, но я написал небольшой пример. Я не знаю, как добавить мой небольшой пример кода в комментарий.
Ответ №2:
Итак, в конце я сделал то, что @niclaslindgren предложил по-своему. Я называю это подходом «KISS» или также известным как «Keep It Simple Stupid». Я также принял во внимание то, что @Steve сказал об использовании глобальных переменных. Я не большой поклонник глобальных переменных, но у них есть свое место в программировании. Приведенное ниже помогло мне:
PASSPORT_VALIDATED = False
class NewUserValidationCamera(Image):
...
...
def update(self, dt):
...
...
if self.names[label] == 'ma' and self._passport_keyword_passed and self._gender_check_passed:
global PASSPORT_VALIDATED
PASSPORT_VALIDATED = True
class MainApp(App):
def __init__(self, **kwargs):
super(MainApp, self).__init__(**kwargs)
Clock.schedule_interval(self.check_for_True, 1.0)
...
...
def check_for_True(self, dt):
if PASSPORT_VALIDATED:
Clock.unschedule(self.check_for_True)
self.send_data_to_the_server()
def send_data_to_the_server(self):
...
...
def register_or_login(self):
if self.login_screen is False:
passport_passed = False
self.validate_passport = NewUserValidationCamera()
self.root.add_widget(self.validate_passport)