【发布时间】:2010-12-05 02:11:19
【问题描述】:
我发现自己最近越来越喜欢 SO。在尝试学习 Python(通过直接进入并尝试从 C# 移植应用程序)时,我遇到了以前从未听说过的东西:线程。当我认为我有一个基本的了解时,我尝试转换程序中压缩一个充满文件(和子目录)的目录的部分。到目前为止,这是我想出的——在一些来源的帮助下,我将在最后列出:
from Queue import Queue
import os
import gtk
import threading
import time
import zipfile
debug = True
class ProduceToQueue( threading.Thread ):
def __init__( self, threadName, queue, window, maximum, zipobj, dirPath ):
threading.Thread.__init__( self, name = threadName )
self.sharedObject = queue
self.maximum = maximum
self.zip = zipobj
self.dirPath = dirPath
self.window = window
global debug
if debug:
print self.getName(), "got all params."
def run( self ):
if debug:
print "Beginning zip."
files = 0
parentDir, dirToZip = os.path.split(self.dirPath)
includeDirInZip = False
#Little nested function to prepare the proper archive path
def trimPath(path):
archivePath = path.replace(parentDir, "", 1)
if parentDir:
archivePath = archivePath.replace(os.path.sep, "", 1)
if not includeDirInZip:
archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1)
return os.path.normcase(archivePath)
for (archiveDirPath, dirNames, fileNames) in os.walk(self.dirPath):
#if debug:
#print "Walking path..."
for fileName in fileNames:
time.sleep( 0.001 )
#if debug:
#print "After a small sleep, I'll start zipping."
filePath = os.path.join(archiveDirPath, fileName)
self.zip.write(filePath, trimPath(filePath))
#if debug:
#print "File zipped - ",
files = files + 1
#if debug:
#print "I now have ", files, " files in the zip."
self.sharedObject.put( files )
#Make sure we get empty directories as well
if not fileNames and not dirNames:
zipInfo = zipfile.ZipInfo(trimPath(archiveDirPath) + "/")
#some web sites suggest doing
#zipInfo.external_attr = 16
#or
#zipInfo.external_attr = 48
#Here to allow for inserting an empty directory. Still TBD/TODO.
outFile.writestr(zipInfo, "")
class ConsumeFromQueue( threading.Thread ):
def __init__( self, threadName, queue, window, maximum ):
threading.Thread.__init__( self, name = threadName )
self.sharedObject = queue
self.maximum = maximum
self.window = window
global debug
if debug:
print self.getName(), "got all params."
def run( self ):
print "Beginning progress bar update."
for i in range( self.maximum ):
time.sleep( 0.001 )
#if debug:
#print "After a small sleep, I'll get cracking on those numbers."
current = self.sharedObject.get()
fraction = current / float(self.maximum)
self.window.progress_bar.set_fraction(fraction)
#if debug:
#print "Progress bar updated."
class MainWindow(gtk.Window):
def __init__(self):
super(MainWindow, self).__init__()
self.connect("destroy", gtk.main_quit)
vb = gtk.VBox()
self.add(vb)
self.progress_bar = gtk.ProgressBar()
vb.pack_start(self.progress_bar)
b = gtk.Button(stock=gtk.STOCK_OK)
vb.pack_start(b)
b.connect('clicked', self.on_button_clicked)
b2 = gtk.Button(stock=gtk.STOCK_CLOSE)
vb.pack_start(b2)
b2.connect('clicked', self.on_close_clicked)
self.show_all()
global debug
def on_button_clicked(self, button):
folder_to_zip = "/home/user/folder/with/lotsoffiles"
file_count = sum((len(f) + len(d) for _, d, f in os.walk(folder_to_zip)))
outFile = zipfile.ZipFile("/home/user/multithreadziptest.zip", "w", compression=zipfile.ZIP_DEFLATED)
queue = Queue()
producer = ProduceToQueue("Zipper", queue, self, file_count, outFile, folder_to_zip)
consumer = ConsumeFromQueue("ProgressBar", queue, self, file_count)
producer.start()
consumer.start()
producer.join()
consumer.join()
outFile.close()
if debug:
print "Done!"
def on_close_clicked(self, widget):
gtk.main_quit()
w = MainWindow()
gtk.main()
这个问题是在大约 7,000 个文件之后程序锁定,我必须强制退出它。我没有尝试过比这更少的文件,但我认为它可能会有同样的问题。此外,进度条不会更新。我知道它很混乱(编程风格上混合了下划线和 CamelCase,以及一般的noobish 错误),但我想不出有什么理由让它不起作用。
这是我得到最多的地方:
http://www.java2s.com/Code/Python/File/Multithreadingzipfile.htm http://www.java2s.com/Tutorial/Python/0340__Thread/Multiplethreadsproducingconsumingvalues.htm
【问题讨论】:
标签: python multithreading progress-bar