Python中的共享变量

时间:2016-01-27 16:42:17

标签: python multithreading python-3.x

我正在尝试创建bot的多个线程并且它们共享一些变量,但我在使共享变量工作时失败了。

以下是代码:

import requests
import sys
import threading
import signal
import time

class bot(threading.Thread):
    terminate = False
    #def __init__(self):
    #   threading.Thread.__init__(self)
    #   self.terminate = False

    def getCode():
        code_lock.acquire()
        work_code = code
        try:
            code += 1
        finally:
            code_lock.release()
        return work_code

    def checkCode(code):
        try:
            #if(code % 1000000 == 0):
            print("Code "+str(code)+" is being checked...\n")
            html = requests.get(url+str(code))
            html.encoding = 'utf-8'
            return not 'Page Not Found' in html.text
        except requests.exceptions.ConnectionError:
            print("Connection Error! Retrying...\n")
            time.sleep(0.5)
        except KeyboardInterrupt:
            logCode(code)
            sys.exit()

    def storeCode(code):
        file_lock.acquire()
        try:
            file.write(code+'\n')
        finally:
            file_lock.release()

    def logCode(code):
        log_lock.acquire()
        try:
            log.write(code+'\n')
        finally:
            log_lock.release()

    #def run(self):
    #   global bots
    #   global url
    #   global file
    #   global log
    #   global code_lock
    #   global file_lock
    #   global log_lock
    while(not terminate):
        code = getCode()
        if(checkCode(code)):
            storeCode(code)
    logCode(code)


def main(code = 0, threads = 16):

    #bots = [threading.Thread(target=bot) for bot in range(threads)]
    bots = []
    url = 'https://test.ing/codes/'
    file = open("valid-codes.txt", "a")
    log = open("log.txt", "a")
    code_lock = threading.Lock()
    file_lock = threading.Lock()
    log_lock = threading.Lock()

    def signal_handler(signal, frame):
        print('Exiting...\n')
        log_lock.acquire()
        try:
            log.write("\n\n"+str(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))+"\n")
        finally:
            log_lock.release()
        for bot in bots:
            bot.terminate = True
        for bot in bots:
            bot.join()
        sys.exit(0)

    #for bot in bots:
    #    bot.start()

    for i in range(threads):
        t = bot()
        bots.append(t)
        t.start()

    signal.signal(signal.SIGINT, signal_handler)
    while True:
        signal.pause()

main(736479509787350, 1)

使用此代码我收到此错误:

  

Traceback(最近一次调用最后一次):文件“bot.py”,第7行,in   

class bot(threading.Thread):   File "bot.py", line 59, in bot

code = getCode()   File "bot.py", line 14, in getCode

code_lock.acquire() NameError: name 'code_lock' is not defined

我不知道是否应该覆盖run(self)的{​​{1}}方法,但是当我尝试它时,它实际上从未运行过bot方法,而且我也收到同样的错误创建的所有线程:run不可调用(我无法看到我可能使用int作为对象)。

另外我不知道我是否正确处理键盘的退出信号,因为你可以看到我试图用int变量来处理它,但我不认为这是问题...

最后一件事,terminate异常没有得到妥善处理,因为它正在说“重试......”,但事实上它不会重试,但我知道这一点,它应该没问题,我会修复后者。

值得一提的是,我不习惯处理多线程,当我处理它时,它是用C或C ++。

修改

我可以通过使用全局变量来使代码工作,但我不想这样做,我更愿意避免使用全局变量。我将变量直接传递给类ConnectionError的实例或通过将数据对象传递给它的尝试到目前为止都没有成功,只要我将变量或辅助对象传递给bot我我无法使用bot作为属性访问它们而没有self. Python声称未定义变量。

以下是更新的代码,但尚未成功:

self.

然而,带有全局变量的工作代码:

import requests
import sys
import threading
import signal
import time

class Shared:
    def __init__(self, code, url, file, log, code_lock, file_lock, log_lock):
        self.code = code
        self.url = url
        self.file = file
        self.log = log
        self.code_lock = code_lock
        self.file_lock = file_lock
        self.log_lock = log_lock

class bot(threading.Thread):
    def __init__(self, data):
        threading.Thread.__init__(self)
        self.terminate = False
        self.data = data

    @classmethod
    def getCode(self):
        self.data.code_lock.acquire()
        work_code = self.data.code
        try:
            self.data.code += 1
        finally:
            self.data.code_lock.release()
        return work_code

    @classmethod
    def checkCode(self, work_code):
        try:
            #if(code % 1000000 == 0):
            print("Code "+str(work_code)+" is being checked...\n")
            html = requests.get(self.data.url+str(work_code))
            html.encoding = 'utf-8'
            return not 'Page Not Found' in html.text
        except requests.exceptions.ConnectionError:
            print("Connection Error! Retrying...\n")
            time.sleep(0.5)
        except KeyboardInterrupt:
            self.logCode(work_code)
            sys.exit()

    @classmethod
    def storeCode(self, work_code):
        self.data.file_lock.acquire()
        try:
            self.data.file.write(work_code+'\n')
        finally:
            self.data.file_lock.release()

    @classmethod
    def logCode(self, work_code):
        self.data.log_lock.acquire()
        try:
            self.data.log.write(work_code+'\n')
        finally:
            self.data.log_lock.release()

    @classmethod
    def run(self):
        while(not self.terminate):
            work_code = self.getCode()
            if(self.checkCode(work_code)):
                self.storeCode(work_code)
        self.logCode(work_code)


def main(code = 0, threads = 16):

    #bots = [threading.Thread(target=bot) for bot in range(threads)]
    bots = []
    url = 'https://www.test.ing/codes/'
    file = open("valid-codes.txt", "a")
    log = open("log.txt", "a")
    code_lock = threading.Lock()
    file_lock = threading.Lock()
    log_lock = threading.Lock()

    data = Shared(code, url, file, log, code_lock, file_lock, log_lock)

    def signal_handler(signal, frame):
        print('Exiting...\n')
        log_lock.acquire()
        try:
            log.write("\n\n"+str(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))+"\n")
        finally:
            log_lock.release()
        for bot in bots:
            bot.terminate = True
        for bot in bots:
            bot.join()
        sys.exit(0)

    #for bot in bots:
    #    bot.start()

    for i in range(threads):
        t = bot(data)
        bots.append(t)
        t.start()

    signal.signal(signal.SIGINT, signal_handler)
    while True:
        signal.pause()

main(736479509787350, 4)

2 个答案:

答案 0 :(得分:1)

您可以尝试将code_lock设为全局,但为什么不将其传递到每个bot类?

t = bot(code_lock)

接下来为您的类创建一个构造函数:

class bot(threading.Thread):
    def __init__(self, code_lock):
       threading.Thread.__init__(self)
       self.code_lock = code_lock

现在,每当您尝试在code_lock课程中使用bot时,请始终在其前面添加selfself.code_lock)。

如果你真的坚持使用全局变量,那么请查看global keyword

答案 1 :(得分:0)

很明显,您正试图从其范围内访问code_lock,可能您可以按照#MartinKonecny建议来解决此问题。

我可以看到即使在修复code_lock问题之后,您的代码也存在很多问题。一旦解决了code_lock问题,您就会在同一个函数code中遇到与变量getCode类似的问题。

在解决所有这些compiled时间问题后,您将面临整个class实施的问题,这不是实施Python类的方法。

最好通过this了解有关python name spacesclasses的更多信息。