簡體   English   中英

Python 3.6 對象/類線程

[英]Python 3.6 Object/Class Threading

我正在尋找使用 Python 3 創建一個“自包含線程類”。

在高層次上,我想要做的是從我的“主”類中生成 50 個異步設備對象,然后根據需要使用它們的方法。 當僅在同步情況下處理對象時,這並不困難,但是當我們轉向異步處理時,很快就會變得模糊。 保持線程自包含在設備類中的主要想法是我的基本(main.py)代碼保持流線型/干凈並且沒有任何線程管理。

在這種情況下,我不打算進行任何資源共享,所以我認為我沒有任何線程鎖問題。

這是一些示例代碼,我希望有人可以提供一些提示或示例,使其成為自線程類(這意味着我不想在 main.py 級別管理線程):

示例 main.py

from deviceworker import Device

availableworkers = {'USA':'services.groupkt.com', 'IND':'services.groupkt.com'}
Activeworkers = []

for name, ip in availableworkers.items():
    Activeworkers.append(Device(name, ip))

for worker in Activeworkers:
    worker.checkcountry()   # asynchronous call - (we don't want to wait for a response)
                            # The idea is to keep this code as clean as possible.

示例對象:deviceworker.py

import urllib.request
import urllib.parse
import json

class Device:
    def __init__(self, name, endpoint, preamble = 'state', port = 80 ):

        self.name = name
        self.connected =False
        self.connection = HTTPConnection(endpoint, preamble, port)
        self.getStatus()

    def getStatus(self, check_for = None):
        self.urlresponse = json.loads(self.connection.GET('get/USA/all')) #Use USA just to verify connection
        if check_for:
            pass

        self.connected = True

    def checkcountry(self):
        print(self.connection.GET('get/%s/all' % self.name))

class HTTPConnection:
    def __init__(self, endpoint, preamble = None, port = 80):

        if preamble: # specificing a version after the port and before method
            self.url = 'http://%s:%s/%s/' % (endpoint, port, preamble)
        else:
            self.url = 'http://%s:%s/' % (endpoint, port)
        print('_init_ url=%s' % self.url)

    def GET(self, operation):
        #try:
            #print('%s%s' % (self.url, operation))
        with urllib.request.urlopen('%s%s' % (self.url, operation)) as f:
             return f.read().decode('utf-8')
        #except Exception as e:
            #raise Exception("GET Request Failed")

為簡單起見,我去除了大部分異常處理。 上面的示例應該可以工作。

- - 更新 - -

所以我想我已經弄清楚了。 仍然沒有從文檔中獲得我期望的parrelism。

import threading
import urllib.request
import urllib.parse
import json
import time


class Device(threading.Thread):
    def __init__(self, name, endpoint, preamble = 'state', port = 80 ):
        threading.Thread.__init__(self)
        self.name = name
        self.connected = False
        self.connection = HTTPConnection(endpoint, preamble, port)
        print('%s: __init__' % self.name)

    def run(self):
        self.getStatus()
        print('%s: hit run()' % self.name)

    def getStatus(self):
        self.urlresponse = json.loads(self.connection.GET('get/USA/all')) #Use USA just to verify connection
        self.connected = True

    def checkcountry(self):
        if (self.name == 'USA'): self.waittime = 10
        else: self.waittime = 0

        print('%s: Getting Codes - wait time: %s' % (self.name, self.waittime))

        start_time=time.time()
        time.sleep(self.waittime)
        result =self.connection.GET('get/%s/all' % self.name)
        elapsed_time=time.time() - start_time
        print('%s: Got Codes - second: %s' % (self.name, elapsed_time))


class HTTPConnection:
    def __init__(self, endpoint, preamble = None, port = 80):
        if preamble: # specificing a version after the port and before method
            self.url = 'http://%s:%s/%s/' % (endpoint, port, preamble)
        else:
            self.url = 'http://%s:%s/' % (endpoint, port)

    def GET(self, operation):
        with urllib.request.urlopen('%s%s' % (self.url, operation)) as f:
             return f.read().decode('utf-8')


DeviceList = {'USA':'services.groupkt.com', 'IND':'services.groupkt.com'}
ActiveDevices = []

DeviceList = {'USA':'services.groupkt.com', 'IND':'services.groupkt.com'}
ActiveDevices = []

for name, ip in DeviceList.items():
    print('main: creating object for: %s' % name)
    newDevice = Device(name, ip)
    ActiveDevices.append(newDevice)
    newDevice.start()

for device in ActiveDevices:
    print('main: calling checkcountry() for: %s' % device.name)
    device.checkcountry()

結果如下:

main: creating object for: USA
USA: __init__
main: creating object for: IND
IND: __init__
main: calling checkcountry() for: USA
USA: Getting Codes - wait time: 10
USA: Got Codes - second: 10.167016744613647
main: calling checkcountry() for: IND
IND: Getting Codes - wait time: 0
IND: Got Codes - second: 0.11001110076904297

我將延遲添加到美國搜索中,我本來希望 IND 首先完成,但它似乎已序列化。

我正在運行這個:

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32

這是一個帶有鎖定的自定義線程示例,對我來說非常有用,比使用事件更好。

在 Colab 中嘗試一下。

import threading,time

i=0

luk=threading.Lock()


global i
global y
global t_num

class special_thread(threading.Thread):
    """This function starts a Thread class"""
    def __init__(self, execute,threadID , name,  daemon,args=(), repetitive=False,kwargs=None, interval_sec=60 ):
        threading.Thread.__init__(self)
        self.daemon = daemon
        self.stopped = threading.Event()
        self.interval_sec = interval_sec
        self.execute = execute
        self.name = name
        if kwargs is None:
            kwargs = {}
        self.args = args
        self.kwargs=kwargs
        self.repetitive=repetitive
        self.threadID = threadID
        print(args)
    def stop(self):
        self.stopped.set()
        self.join()

    def run(self):
        if self.repetitive:
            while not self.stopped.wait(self.interval_sec):
                self.execute(*self.args,**self.kwargs)
        else:
            self.execute(*self.args,**self.kwargs)


def center(t_num):
    y=0
    
    luk.acquire()
    caller = inspect.getouterframes(inspect.currentframe())[1][3]
    print(' {} is aquiring by {} '.format( caller,  str(time.ctime())))
    y+=t_num
    
    print( "Inside %s()" % caller)
    print('thread number is ',t_num,y)
    time.sleep(2*t_num)
    luk.release()
    print(' {} is releasing  by {} '.format( caller,  str(time.ctime())))

def target_uno():
  t_num=1
  center(t_num)

def target_dos():
  t_num=2
  center(t_num)


target_uno=special_thread(execute=target_uno, args=(),repetitive=True, interval_sec=1,threadID=10004,
                                                  name='target_uno',
                                                  daemon=False )

target_dos=special_thread(execute=target_dos, args=(),repetitive=True, interval_sec=1,threadID=10004,
                                                  name='target_dos',
                                                  daemon=False )

if __name__ == "__main__":

  target_uno.start()
  target_dos.start()
  time.sleep(20)
  target_uno.stop()
  target_dos.stop()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM