Ошибка имени многопроцессорной обработки Tkinter: имя «область регистрации» не определено

#python #tkinter #multiprocessing

Вопрос:

Я использую следующий код, но я получаю «Ошибка имени: имя» логарифмическая область «не определено»

 from tkinter import *
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import time
import multiprocessing
from multiprocessing import Queue
import os
from tkinter import ttk
import logging
import datetime



curr_dir = os.getcwd()

def browserRun():
    global curr_dir
    timenow = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    logname = rf'{curr_dir}LogsLog-{timenow}.txt'
    logging.basicConfig(filename=logname,
                        filemode='a',
                        format='%(asctime)s: %(message)s',
                        datefmt='%d-%m-%Y %I:%M:%S %p',
                        level=logging.INFO,
                        force=True)
    while True:
        global driver
        options = Options()
        options.binary_location = r'D:DownloadsChromedriverbrowserchrome.exe'
        driver = webdriver.Chrome(executable_path=r'D:DownloadsChromedriverchromedriver.exe', options=options)
        driver.get('http://google.com')
        logging.info(f"Logging to gmail")
        loggingtoUI(logname)
        time.sleep(5)
        driver.find_element(By.XPATH, '//input[@name="q"]').send_keys("Hello World")
        time.sleep(5)
        driver.close()
        driver.quit()

def start():
    global executor
    pqueue = Queue()
    executor = [multiprocessing.Process(target=browserRun) for _ in range(1)]
    for p in executor:
        p.daemon = True
        p.start()


def loggingtoUI(logname):
    global myfile
    global logarea
    with open(logname, "r") as myfile:
        try:
            MyText2 = myfile.read()
            logarea.config(state='normal')
            logarea.delete('1.0', END)
            logarea.insert(INSERT, MyText2)
            logarea.see("end")
            logarea.config(state='disabled')
        finally:
            myfile.close()




def stop():
    global executor
    for p in executor:
        p.terminate()
    # os.system("taskkill /F /IM chromedriver.exe /T")
    os.system("taskkill /F /IM CHROME.exe /T")


if __name__ == '__main__':
    global logarea
    root = Tk()
    notebook = ttk.Notebook(root, style='lefttab.TNotebook')
    tab1 = ttk.Frame(notebook)
    tab2 = ttk.Frame(notebook)
    notebook.add(tab1, text="Home")
    notebook.add(tab2, text="Settings")
    notebook.pack(fill=BOTH, expand=True)
    button = Button(tab1, text="start", command=start)
    button.place(x=20, y=20)
    button1 = Button(tab1, text="stop", command=stop)
    button1.place(x=70, y=20)
    logarea = Text(tab1, height=25, width=40, wrap='word', state='disabled')
    logarea.place(x=120, y=40)
    root.geometry("500x500")
    root.mainloop()
 

Я установил логарифмическую область в глобальную, но все равно получаю ошибку имени, я попытался установить логарифмическую область как глобальную при запуске и загрузке кода, но ничего не работает.

Проблема возникает, когда я вызываю loggingtoUI в другой функции. Любая помощь будет признательна.

Комментарии:

1. во — первых , вам не нужно использовать global logarea , во-вторых, вам не нужно использовать try/finally with контекстный менеджер, потому что это именно то, что он делает неявно. и logarea определяется

2. Матисс, Спасибо за помощь, но это не сработало, я снимаю try/finally global logarea , но все равно это видно NameError: name 'logarea' is not defined , это происходит на logarea.config(state='normal')

3. Данные не передаются между процессами.

4. acw1668, Спасибо за помощь, когда я добавляю print после MyText2 = myfile.read() того, как смогу увидеть прочитанные данные

5. logarea не разделяется между процессами, и вы даже не можете поделиться им, потому что он не поддается маринованию (ничего tkinter такого нет), вам, вероятно, нужно использовать multiprocessing.Queue или multiprocessing.Manager обмениваться данными с основным процессом и использовать .after «цикл» для обновления текстового виджета

Ответ №1:

Наконец-то нашел ответ, спасибо за помощь, ребята

 from queue import Empty, Full
import tkinter as Tk
import multiprocessing
from tkinter import ttk
from tkinter import *
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import logging
import datetime
import time
import os
import undetected_chromedriver.v2 as uc
import random
import tempfile



logname = ''
curr_dir = os.getcwd()

class GuiApp(object):
   def __init__(self, q):
      self.root = Tk()
      self.notebook = ttk.Notebook(self.root, style='lefttab.TNotebook')
      self.tab1 = ttk.Frame(self.notebook)
      self.tab2 = ttk.Frame(self.notebook)
      self.notebook.add(self.tab1, text="Home")
      self.notebook.add(self.tab2, text="Settings")
      self.notebook.pack(fill=BOTH, expand=True)
      self.button = Button(self.tab1, text="start", command=self.start)
      self.button.place(x=20, y=20)
      self.button1 = Button(self.tab1, text="stop", command=self.stop)
      self.button1.place(x=70, y=20)
      self.logarea = Text(self.tab1, height=25, width=40, wrap='word', state='disabled')
      self.logarea.place(x=120, y=40)
      self.root.geometry("500x500")
      self.root.after(100, self.CheckQueuePoll, q)

   def CheckQueuePoll(self, c_queue):
      global logname
      try:
         MyText2 = c_queue.get(0)
         self.logarea.config(state='normal')
         self.logarea.delete('1.0', END)
         self.logarea.insert('end', MyText2)
         self.logarea.config(state='disabled')
      except Empty:
         pass
      finally:
         self.root.after(100, self.CheckQueuePoll, c_queue)

   def start(self):
      global executor
      executor = [multiprocessing.Process(target=GenerateData,args=(q,)) for _ in range(2)]
      for p in executor:
         p.start()
      # t1 = multiprocessing.Process(target=GenerateData,args=(q,))
      # t1.start()

   def stop(self):
      # t1.terminate()
      for p in executor:
         p.terminate()
      os.system("taskkill /F /IM chromedriver.exe /T")
      # os.system("taskkill /F /IM CHROME.exe /T")


def GenerateData(q):
   global logname
   global curr_dir
   timenow = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
   logname = rf'{curr_dir}LogsLog-{timenow}.txt'
   logging.basicConfig(filename=logname,
                          filemode='a',
                          format='%(asctime)s: %(message)s',
                          datefmt='%d-%m-%Y %I:%M:%S %p',
                          level=logging.INFO,
                          force=True)
   while True:
      options = uc.ChromeOptions()
      rand_num = random.randint(0000, 9999)
      temp = tempfile.gettempdir()
      temp_dir = rf'{temp}/temp{rand_num}'
      options.add_argument(f'--user-data-dir={temp_dir}')
      options.add_argument('--no-first-run --no-service-autorun --password-store=basic --disable-notifications')
      options.binary_location = rf'{curr_dir}driversBrowserchrome.exe'
      driver = uc.Chrome(executable_path=rf'{curr_dir}driverschromedriver.exe', options=options)
      driver.get('http://google.com')
      logging.info(f"Logging to gmail")
      f = open(logname, "r")
      q.put(f.read())
      time.sleep(5)
      driver.find_element(By.XPATH, '//input[@name="q"]').send_keys("Hello World")
      time.sleep(5)
      driver.close()
      driver.quit()

if __name__ == '__main__':
   q = multiprocessing.Queue()
   q.cancel_join_thread()  # or else thread that puts data will not term
   gui = GuiApp(q)
   gui.root.mainloop()