Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 11, 2010 06:41:31

dartNNN
От:
Зарегистрирован: 2009-12-08
Сообщения: 199
Репутация: +  0  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Никак не получается организовать запись в файл из другого потока. Пишу вот так

class Dumper(threading.Thread):
def __init__(self, to_dump, dir, fname):
self.to_dump = to_dump
self.dir = dir
self.fname = fname
threading.Thread.__init__(self)
self.daemon = True

def run(self):
some_rlock = threading.RLock()
with some_rlock:
f=open(self.dir+"\\Notes\\" + self.fname,"wb")
pickle.dump(self.to_dump,f)
f.close()
И вызываю так:
    def dump(self):
Dumper(self.MainNote, self.workdir, self.fname).start()
Цель: сделать поток-демон, который после закрытия программы сохранял бы все данные.
Цель №2: разобраться с потоками.

Результат: во время работы основной программы (тоже возможно сохранение данных) все работает. Но после выхода из программы файл с данными пустой.

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



Офлайн

#2 Апрель 11, 2010 11:07:28

ziro
От:
Зарегистрирован: 2009-08-13
Сообщения: 225
Репутация: +  8  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Нормально все работает. У Вас просто поток не успевает сдампить данные пока программа закрывается - это типичная ошибка начинающих в multithreading (я на эти грабли еще в delphi наступал).

Для того, чтобы работало нормально - необходимо дождаться окончания выполнения метода run.

Самый простой способ - это вызов Thread.join() после запуска потока.

Или внутри потока по окончании процесса сохранения кидать событие (threading.Event) а в вызывающем потоке его ждать. Само событие передавать как аргумент в конструкторе ессно. Но такая схема обычно используется, если в рабочий поток периодически чего-нить через Queue кидается.

Да кстати, лок в Вашем случае - как собаки пятая нога - они для управления доступом к общим данным между различными тредами - а у Вас все внутри одного треда делается.



Офлайн

#3 Апрель 11, 2010 11:29:29

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Вы не поняли. Ему нужен daemon thread, который будет работать после окончания основной программы.



Офлайн

#4 Апрель 11, 2010 11:42:55

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

К сожалению это невозможно. Все daemon треды убиваются автоматически при завершении основной программы. Так что если уберете daemon = True, то все будет работать. Правда основная программа будет ждать пока ваш тред завершится, а это не то, что вы хотели.



Офлайн

#5 Апрель 11, 2010 12:06:02

ziro
От:
Зарегистрирован: 2009-08-13
Сообщения: 225
Репутация: +  8  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Так что если уберете daemon = True, то все будет работать.
Кстати да - так еще проще.



Офлайн

#6 Апрель 11, 2010 12:13:51

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Если у вас *NIX, то можно просто форкнуться и в форкнутом процессе запустить сохранение данных. Основной процесс при этом завершить, а форкнутый отработает и выйдет после сохранения данных.



Офлайн

#7 Апрель 11, 2010 13:59:40

dartNNN
От:
Зарегистрирован: 2009-12-08
Сообщения: 199
Репутация: +  0  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Спасибо за разъяснения, но по ходу еще вопрос: пробовал без daemon = True, но ничего не менялось, т.е. прога также завершалась, файл по окончании также пуст был.



Офлайн

#8 Апрель 11, 2010 14:59:52

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Запись файла в другом потоке

Вот мой код на основе вашего примера. Из вывода видно, что главный тред ждет пока другой завершится:

import threading
import os
import sys
import time

class Dumper(threading.Thread):
def __init__(self, to_dump, dire, fname):
self.to_dump = to_dump
self.dire = dire
self.fname = fname
threading.Thread.__init__(self)
#self.daemon = True

def run(self):
time.sleep(2)
some_rlock = threading.RLock()
with some_rlock:
f = open(os.path.join(self.dire, self.fname), "w")
f.write('daemon is started %s\n' % time.asctime())
f.write(self.to_dump)
time.sleep(2)
f.write('daemon is done %s\n' % time.asctime())
f.close()


print 'main is started', time.asctime()
dumper = Dumper('text1\n', '.', 'dumper.out')
dumper.start()
print 'main is stopped', time.asctime()
вывод:
$ python2.6 test24.py 
main is started Sun Apr 11 14:59:20 2010
main is stopped Sun Apr 11 14:59:20 2010
$ cat dumper.out
daemon is started Sun Apr 11 14:59:22 2010
text1
daemon is done Sun Apr 11 14:59:24 2010



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version