Найти - Пользователи
Полная версия: не могу подружить vultiprocessing , классы и Tkinter
Начало » Python для новичков » не могу подружить vultiprocessing , классы и Tkinter
1
@cckyi_boxxx
к сожалению все примеры что нашел в гугле не рассматривают мою ситуацию а переписывать овер 500 строк кода на 80% слишком муторно посему прошу вашей помощи

побыстрому набросал более простой код с аналогичной ситуацией , вот он :

#!/usr/bin/python
#-*- coding: utf-8 -*-
import multiprocessing , time
from Tkinter import *
### любая глобальная переменная
global some_var , var2
some_var = 'lol'
var2 = True
### любая функция
def somefunc():
    return 'aaa'
    
class someclass(object):
    def __init__(self):
        ### любая переменная в конструкторе
        self.do = 'initalize'
        ### создаем в ткинтере примитивный гуй
        self.root = Tk()
        self.root.geometry('300x300+100+100')
        self.frm = Frame(self.root)
        self.frm.place(x = 0 , y = 0 , width = 300 , height = 300)
        # кнопка которая должна запустить процесс
        self.butt = Button(self.root , text = 'test multiprocessing' , command = self.button_command)
        self.butt.place(x = 10 , y = 10)
        # то что должно обрабатываться процессом
        self.txt = Text(self.root)
        self.txt.place(x = 10 , y = 50 , width = 280 , height = 240)
        
    # метод запускаемая в процессе
    def testfunc(self):
        self.gprint(self.do)
        writestr = some_var + somefunc() + '\n'
        for x in xrange(0 , 100) :
            self.gprint( str(x) + ') ' + writestr)
            time.sleep(0.1)
        var2 = False # меняю значение глобальной переменной
    
    # пишет в text виджет (self.txt)
    def gprint(self , value):
        self.txt.insert(END, value) 
        self.txt.see(END) # перемотка к концу выхлопа
    
    
    # метод вызываеться при нажатии на кнопку и должна запустить в отдельном процессе метод testfunc
    def button_command(self):
        proc = multiprocessing.Process(target = self.testfunc)
        proc.start()
if __name__ == '__main__' :
    w = someclass()
    w.root.mainloop()


суть в следующем : требуеться что-бы все методы класса имели доступ к основному коду (функциям и глобальным переменным) и к переменным и методам класса ,которые так-же могут иметь доступ к “внешнему миру” , при этом часть логики перенесена в класс с гуем , задача состоит в том что-бы в отдельном процессе выполнялась сложная задача ( в примере метод button_command ) , при этом не вешала гуй и имела доступ ко всему что ей потребуеться для успешного выполнения задачи , но как я ни старался у меня следующий лог ошибки :

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Users\shipper\Documents\Aptana Studio 3 Workspace\temp\python.su.py", line 51, in button_command
proc.start()
File "C:\Python27\lib\multiprocessing\process.py", line 130, in start
self._popen = Popen(self)
File "C:\Python27\lib\multiprocessing\forking.py", line 277, in __init__
dump(process_obj, to_child, HIGHEST_PROTOCOL)
File "C:\Python27\lib\multiprocessing\forking.py", line 199, in dump
ForkingPickler(file, protocol).dump(obj)
File "C:\Python27\lib\pickle.py", line 224, in dump
self.save(obj)
File "C:\Python27\lib\pickle.py", line 331, in save
self.save_reduce(obj=obj, *rv)
File "C:\Python27\lib\pickle.py", line 419, in save_reduce
save(state)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\multiprocessing\forking.py", line 67, in dispatcher
self.save_reduce(obj=obj, *rv)
File "C:\Python27\lib\pickle.py", line 401, in save_reduce
save(args)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 548, in save_tuple
save(element)
File "C:\Python27\lib\pickle.py", line 331, in save
self.save_reduce(obj=obj, *rv)
File "C:\Python27\lib\pickle.py", line 419, in save_reduce
save(state)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 725, in save_inst
save(stuff)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 725, in save_inst
save(stuff)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 725, in save_inst
save(stuff)
File "C:\Python27\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Python27\lib\pickle.py", line 649, in save_dict
self._batch_setitems(obj.iteritems())
File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
save(v)
File "C:\Python27\lib\pickle.py", line 313, in save
(t.__name__, obj))
PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x019BF1A8>
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main
self = load(from_parent)
File "C:\Python27\lib\pickle.py", line 1378, in load
return Unpickler(file).load()
File "C:\Python27\lib\pickle.py", line 858, in load
dispatch[key](self)
File "C:\Python27\lib\pickle.py", line 880, in load_eof
raise EOFError
EOFError

как такое реализовать понятия не имею , помогите кто может

4kpt_II
Помочь то оно не сложно, но тема должна то быть не здесь
А если серьезно, то разделение на отдельные потоки в Tkinter выполняется совершенно другим образом. Что threding, что multiprocessing тут не помогут.
@cckyi_boxxx
Помочь то оно не сложно, но тема должна то быть не здесь

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

А если серьезно, то разделение на отдельные потоки в Tkinter выполняется совершенно другим образом. Что threding, что multiprocessing тут не помогут.

а эту фразу вовсе не понял , задача проста есть несколько ресурсоемких процессов которые выполняються овер полчаса и должны работать параллельно и общаться с главным процессом время от времени , при этом еще и гуй “вешать” не хотелось-бы
4kpt_II
Что во второй фразе Вас смутило? Механизм создание отдельного потока событий в Tkinter осуществляется без использования threading и multiprocessing. Если использовать их, то все равно на выходе получаем подвисание основного потока событий.

P.S. Я так и не понял, что Вам надо. Вы хотите, чтобы можно было запустить задачу, которая бы выполнялась в отрыве от основного потока событий. При этом не было подвисания GUI и можно было бы выполнять остальные задачи. Я Вас правильно понял?
@cckyi_boxxx
абсолютно верно , только что можно сделать отдельный поток через ткинтер я никогда и не слышал , а как это делаеться на практике и вовсе понятия не имею
4kpt_II
Для этого нужно использовать рекурсию с конструкцией .afer()
Пример

# -*- coding: utf-8 -*-
import Tkinter
import time
#
tm = time.time()
def call_passive(event):
    print u"Выполнен шаг процесса."
    # Будет запускаться 10 секунд через каждую секунду
    if time.time() - tm < 10:
        root.after(1000, call_passive, event)
#
def call_active(event):
    print u"Пассивное нажатие в процессе."
#
def keybind(event):
    print u"Нажата клавиша - ", event.keysym
#
root = Tkinter.Tk()
root.geometry("400x400+100+100")
root.bind("<Any-KeyRelease>", keybind)
#
bt_free = Tkinter.Button(root, width=20, text="Свободно нажимаем")
bt_free.place(relx=0.5, rely=0.33, anchor="center")
bt_free.bind("<ButtonRelease-1>", call_active)
#
bt_proc = Tkinter.Button(root, width=20, text=u"Запускаем процесс")
bt_proc.place(relx=0.5, rely=0.66, anchor="center")
bt_proc.bind("<ButtonRelease-1>", call_passive)
#
root.mainloop()

P.S. Будут вопросы - пишите…
@cckyi_boxxx
код поразил , сейчас уже реализовал на мукльтипроцессинге заставив код работать не в классе а с обьектом класса , в следующем проекте буду ковырять , сенкс
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB