初学者程序使用线程和类设计

时间:2011-12-13 08:10:33

标签: python multithreading class

似乎这个问题太长了,任何人都无法发表评论......我正试图在名为'laulau.py'的模块中打印出一些文本和进度条。这是一段显示简单版本的测试代码。我的目标是只有一个线程,并向其发送信息。我的问题是 最好的方法是什么?

file1(test.py)

#!/usr/bin/env python

from laulau import laulau
import time

print "FIRST WAY"

total=107
t=laulau()
t.echo('this is text')
t.setbartotal(total)
for a in range(1,total):
    t.updatebar(a)
    time.sleep(0.01)
time.sleep(1)
print
print "\ndone loop\n"
t.stop()
time.sleep(1)

print "SECOND WAY"

with laulau().echo("this is text"):
    time.sleep(1)
    print "\nyes this is working\n"
    time.sleep(2)

file2:laulau.py

#!/usr/bin/env python
# vim:fileencoding=utf8

from __future__ import division
import time
import string
import threading
from sys import stdout


class laulau(threading.Thread):

    def __init__(self, arg=None):
        super(laulau,self).__init__()
        self._stop = False
        self.block='█'
        self.empty='□'
        self.TEMPLATE = ('%(progress)s%(empty)s %(percent)3s%%')
        self.progress = None
        self.percent = 0
        self.bar_width=30
        self.bartotal=None

    def run (self):
        # start thread for text
        while not self._stop:
            if self.bartotal is None:
                print self.arg,
                stdout.flush()
                time.sleep(0.3)
            else:
                self.progress = int((self.bar_width * self.percent) / 100)
                self.data = self.TEMPLATE % {
                        'percent': self.percent,
                        'progress': self.block * self.progress,
                        'empty': self.empty * (self.bar_width - self.progress),
                }

                stdout.write('\033[%dG'%1 + self.data + self.arg)
                stdout.flush()
                time.sleep(0.1)

    def setbartotal(self,total):
        # set progress bar total
        if self.bartotal is None:
            self.bartotal = total
            self.updatebar(0)

    def updatebar (self,num):
        self.num=num
        self.percent = self.percentage(self.num)

    def percentage (self,numagain):
        return int((numagain/self.bartotal)*100+1)

    def echo (self,arg="Default"):
        #self.thread_debug()
        self.arg=arg
        self._stop = False
        self.start()
        return self

    def thread_debug(self):
        print "threading enumerate :%s"%threading.enumerate()
        print "current thread :%s"%threading.currentThread()
        print "thread count (including main thread):%s"%threading.activeCount() 

    def stop(self):
        self._stop = True

    def stopped(self):
        return self._stop == True

    def __enter__(self):
        print "\nwe have come through the enter function\n"
        return self

    def __exit__(self, type, value, traceback):
        self._stop = True
        print "\nwe have exited through the exit function\n"
        return isinstance(value, TypeError)

在某些情况下,第二种方式可行。例如,当我打印一些文本时,只需要线程在它结束时死掉,但是当它需要更新发送到它时,不是在进度条的情况下。虽然这一切都有用,而且我学到了很多,但我仍然无法弄清楚如何以我想要的方式封装这个类。由于我只想要一个线程,我不需要继续实例化该类,我只需要执行一次。

所以,例如我理想的方式只有三个功能:

  • 1控制文本,打开进度条等(从一个解析后的字符串中)
  • 2设置进度条总计
  • 3设置进度条迭代

我需要更改类中的两个变量(对于进度条)

  • 一个用于总计
  • 一个用于迭代

......并且从那里算出了百分比。

首先我认为我应该通过继承线程中的类来启动线程,然后在查看threading.Thread(target=blah,etc)之后我看不到如何使用多个函数,然后我发现我可以放那里的类​​名threading.Thread(target=laulau),这将启动一个带有类的线程,但后来我被困在如何发送该线程信息,因为我没有将它分配给'{名称',如{{ 1}}

我的第二个想法是在我的模块中有类之外的函数,但是因为我需要多个函数,所以我把它添加到laulau.py的开头也有点困惑:

t=laulau()

第一个函数创建了类的实例,但前面的函数无法更改其中的任何变量。和然后我遇到了this等函数属性。

def eko (arg):
    t=laulau()  
    t.echo(arg)

def barupate(iteration):
    t.updatebar(a)

def bartotal():
    t.setbartotal(a)

然后我开始思考也许我可以以某种方式使用它,但之前从未遇到过它。

理想情况下ID就像这样:

class Foo:
    @webmethod
    def bar(self, arg1, arg2):
         ...

def webmethod(func):
    func.is_webmethod = True
    return func

如果你了解python,你现在可能很有趣,但请记住,我是一个非常专业的初学者,每天都在学习,很多都归功于这个网站。欢呼任何帮助!

编辑:应该添加我知道进度条模块和各种其他食谱,但我是为了学习和有趣的目的而做到这一点:)

1 个答案:

答案 0 :(得分:1)

如果您只需要打印进度条,请使用sys模块,如下所示:

import sys
import time

progress = "0"                                 #this is an int meant to represent 0-100 percent as 0-100
old = "0"                                      #this represents the last updates progress, so that this update only adds the difference and not the full progress

def updatebar(progress,old):
    for item in range((progress-old)/2)        #this takes the range of progress but divides it by 2, making the progress bar 50 characters long
    sys.stdout.write("-")                      #to change the character used to fill the progress bar change the "-" to something else
    sys.stdout.flush()

#you may not want to use a while loop here, this just has an example of how to use the update function as it adds one to the progress bar every second
while True:
    progress += 1
    updatebar(progress,old)
    old = progress                             #sets the old progress as the current one, because next iteration of the while loop the previous progress will be this one's current progress.
    time.sleep(1)