0

私のプログラムの目的は、スレッドを含むファイルをダウンロードすることです。ユニットを定義し、len / unitスレッドを使用して、lenはダウンロードされるファイルの長さです。

私のプログラムを使用すると、ファイルをダウンロードできますが、スレッドが停止していません。理由がわかりません。

これは私のコードです...

#! /usr/bin/python

import urllib2
import threading
import os
from time import ctime

class MyThread(threading.Thread):
 def __init__(self,func,args,name=''):
  threading.Thread.__init__(self);
  self.func = func;
  self.args = args;
  self.name = name;
 def run(self):
  apply(self.func,self.args);

url = 'http://ubuntuone.com/1SHQeCAQWgIjUP2945hkZF';
request = urllib2.Request(url);
response = urllib2.urlopen(request);
meta = response.info();
response.close();
unit = 1000000;
flen = int(meta.getheaders('Content-Length')[0]);
print flen;
if flen%unit == 0:
 bs = flen/unit;
else :
 bs = flen/unit+1;
blocks = range(bs);
cnt = {};
for i in blocks:
 cnt[i]=i;
def getStr(i):
 try:
  print 'Thread %d start.'%(i,);
  fout = open('a.zip','wb');
  fout.seek(i*unit,0);
  if (i+1)*unit > flen:
   request.add_header('Range','bytes=%d-%d'%(i*unit,flen-1));
  else :
   request.add_header('Range','bytes=%d-%d'%(i*unit,(i+1)*unit-1));
  #opener = urllib2.build_opener();
  #buf = opener.open(request).read();
  resp = urllib2.urlopen(request);
  buf = resp.read();
  fout.write(buf);
 except BaseException:
  print 'Error';
 finally :
  #opener.close();
  fout.flush();
  fout.close();
  del cnt[i];
# filelen = os.path.getsize('a.zip');
 print 'Thread %d ended.'%(i),
 print cnt;
# print 'progress : %4.2f'%(filelen*100.0/flen,),'%';
def main():
 print 'download at:',ctime();
 threads = [];
 for i in blocks:
  t = MyThread(getStr,(blocks[i],),getStr.__name__);
  threads.append(t);
 for i in blocks:
  threads[i].start();
 for i in blocks:
#  print 'this is the %d thread;'%(i,);
  threads[i].join();
 #print 'size:',os.path.getsize('a.zip');
 print 'download done at:',ctime();
if __name__=='__main__':
 main();

スレッドが停止しない理由を誰かが理解するのを手伝ってくれませんか。

4

1 に答える 1

1

コード例は非常に面倒でわかりにくいため、実際に対処することはできませんが、スレッドが終了していないことがわかる潜在的な理由は、リクエストが停止して終了しないことです。urllib2リクエストにかかる時間を指定できます。

自分のコードに推奨するのは、作業をキューに分割し、(可変数ではなく)固定数のスレッドを開始し、完了するまでワーカースレッドに作業をピックアップさせることです。httpリクエストにタイムアウトを設定します。タイムアウトが期限切れになった場合は、再試行するか、作業をキューに戻します。

キュー、固定数のワーカー、およびそれらの間の同期プリミティブを使用する方法の一般的な例を次に示します。

import threading
import time
from Queue import Queue

def worker(queue, results, lock):
    local_results = []
    while True:
        val = queue.get()
        if val is None:
            break

        # pretend to do work
        time.sleep(.1)
        local_results.append(val)

    with lock:
        results.extend(local_results)
        print threading.current_thread().name, "Done!"


num_workers = 4

threads = []
queue = Queue()
lock = threading.Lock()
results = []

for i in xrange(100):
    queue.put(i)

for _ in xrange(num_workers):

    # Use None as a sentinel to signal the threads to end
    queue.put(None)

    t = threading.Thread(target=worker, args=(queue,results,lock))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

print sorted(results)

print "All done"
于 2012-12-21T03:01:35.963 に答える