给方法加了python线程锁,第一次会起作用,但是一段时间之后就锁就失效了

背景

背景:1.多线程,每个线程打开了chrome浏览器登录不同的账号进行操作,需要微信扫码登录,我会把二维码发送给微信好友,微信好友在手机端长按二维码识别登录。
2. 整个流程需要不间断24h运行

问题

问题:1. 线程是同步打开的,因为电脑端的微信只有一个,这个发送的方法需要加锁,我加了锁,第一次调用的时候锁成功的。但是运行有段时间之后session过期,需要重新发送,这个时候发送的时候锁就失效。
2. 出现的现象是:输入本地保存的二维码路径多线程一起输,就直接输错了。需要在第二次调用的时候也有锁

代码

def sent_pic(self, channelShopId, path):
    name_dict = {'a':'b','c':'d'}
    lock = threading.Lock()
    lock.acquire()
    self.connect_wechat()
    print("开始发送登录二维码给爱逛管理员")
    wx_name = name_dict.get(channelShopId)
    try:
        while 1 == 1:
            if self.win.child_window(title=wx_name, control_type='Text').exists(timeout=1):
                print("点击管理员昵称")
                time.sleep(3)
                self.click_one(title=wx_name, control_type='Text')
                time.sleep(1)
                self.click_one(title="发送文件", control_type='Button')
                print("点击发送文件")
                time.sleep(1)
                try:
                    self.win.child_window(title="文件名(N):", class_name='Edit').type_keys(path)
                    print("输入文件名")
                except Exception as e:
                    print()
                time.sleep(1)
                try:
                    self.win.child_window(class_name='Button', title='打开(O)').click_input()
                    print("点击打开")
                except Exception as e:
                    print()
                time.sleep(1)
                self.click_one(title="sendBtn", control_type='Button')
                print("点击发送")
                time.sleep(1)
                break
            else:
                print("当前界面未找到微信联系人:%s" % wx_name)
                time.sleep(random.randint(30, 60))
    except Exception as e:
        print(e)
        send_error_msg(channelShopId, "sent_pic", e)
    lock.release()
  • 锁需要所有线程持有同一个实例,这样才能在线程间互相限制。但是你发出来的这个方法应该已经是线程里面执行的方法了吧?你在方法里面获取了锁,导致每个线程拿了各自的锁实例,每个锁实例是独立工作的,互相之间并不能限制,导致锁本身就没生效
  • 可以将锁变成一个类变量或者传递到线程里,保证每个线程拿到的锁实例是同一个就好了

声明线程,同时代码前面声明了global

# 开始执行
self.g = globals()
for channelShopId in channelShopIdList:
    driver = driverList[channelShopIdList.index(channelShopId)]
    self.g['lock'] = threading.Lock()
    thread.append(threading.Thread(target=self.run_start, args=(driver, channelShopId)))

使用锁:

def sent_pic(self, channelShopId, path):
        name_dict = {'a':'b','c':'d'}

    # lock = threading.Lock()
    self.g['lock'].acquire()
    self.connect_wechat()
    print("开始发送登录二维码给爱逛管理员")
    wx_name = name_dict.get(channelShopId)
    try:
        while 1 == 1:
            if self.win.child_window(title=wx_name, control_type='Text').exists(timeout=1):
                print("点击管理员昵称")
                time.sleep(3)
                self.click_one(title=wx_name, control_type='Text')
                time.sleep(1)
                self.click_one(title="发送文件", control_type='Button')
                print("点击发送文件")
                time.sleep(1)
                try:
                    self.win.child_window(title="文件名(N):", class_name='Edit').type_keys(path)
                    print("输入文件名")
                except Exception as e:
                    print()
                time.sleep(1)
                try:
                    self.win.child_window(class_name='Button', title='打开(O)').click_input()
                    print("点击打开")
                except Exception as e:
                    print()
                time.sleep(1)
                self.click_one(title="sendBtn", control_type='Button')
                print("点击发送")
                time.sleep(1)
                break
            else:
                print("当前界面未找到微信联系人:%s" % wx_name)
                time.sleep(random.randint(30, 60))
    except Exception as e:
        print(e)
        send_error_msg(channelShopId, "sent_pic", e)
    self.g['lock'].release()
  • 你可以直接写个类来存这个锁,比如
class GlobalLock:
  sent_pic_lock = threading.Lock()
  • 后续使用就直接用GlobalLock.sent_pic_lock就行了
  • 因为python的类对象是进程内共享的,这样多个线程都能拿到同一个
关闭