【问题标题】:Asyncio unexpected condition race problemAsyncio 意外条件竞争问题
【发布时间】:2021-09-27 12:42:40
【问题描述】:

我在使用 asyncio 和 aiohttp 时遇到了一个奇怪的问题。我可能正在经历比赛状态。我从具有不同 x 变量的循环中运行此异步函数 cvim_vlan_list 两次。但是我正在经历的是,我从函数中的第一个 await 获得的令牌以某种方式在代码中间被重写 - 这意味着 cvim_headers 对象是相同的,不应该是。我把 cmets 放在代码旁边。我真的不知道为什么要重写这个值。

初始化循环

        self.loop = asyncio.new_event_loop()
        checks_to_run = self.returnChecksBasedOnInputs()
        self.loop.run_until_complete(asyncio.wait_for(self.run_all_checks_async(checks_to_run),180))
        asyncio.set_event_loop(self.loop)

在我传递循环的文件中

x = 0
cvim_tasks = []
for cvim_scan_container in self.constants.cvim_scan_containers:
    cvim_tasks.append(self.loop.create_task(self.cvim_vlan_list(cvim_scan_container,x)))
    x += 1
        
await asyncio.gather(*cvim_tasks)



async def cvim_vlan_list(self, cvim_scan_container, x):
        cvim_vlans = []
        network_ids = []
        # 2. Get cvim_container_token for each az
        cvim_headers = self.constants.cvim_headers
        cvimAuthenticationData="{\"auth\": {\"methods\": [\"credentials\"], \"credentials\": {\"username\": \"calipso\",\"password\": \"" + self.constants.azpasswords[x] + "\"}}}\r\n"
        response = await apiCaller().callAndReturnJson("POST",f"https://{cvim_scan_container}/auth/tokens",headers=cvim_headers, session=self.session,payload=cvimAuthenticationData,log=self.log)
        cvim_container_token = response['token']

        #update headers with token
        cvim_headers['X-Auth-token'] = cvim_container_token  ############## HERE ARE cvim_headers different
        # 3. RUN SCAN in each az
        scanData="{\"env_name\" : \"cvim-fci-pod"+str(x+1)+"-muc-eip\",\r\n\"log_level\": \"warning\"\r\n}"
        response = await apiCaller().callAndReturnJson("POST",f"https://{cvim_scan_container}/scans",headers=cvim_headers, session=self.session,payload=scanData,log=self.log)
        scan_id = response['id']

        ############## HERE ARE cvim_headers the same
        ############## The token from second def execution is also in the first def execution, that means cvim_headers are same which results to error from API 
        # 4. Periodically check if scan is completed
        isScanRunning = True
        while isScanRunning == True:
            self.log.info('checking scan')
            
            self.log.info(cvim_headers) ########  HERE THE token from second def execution is also in the first def execution, that means cvim_headers are same which results to error from API 
            response = await apiCaller().callAndReturnJson("GET",f"https://{cvim_scan_container}/scans?env_name=cvim-fci-pod"+str(x+1)+"-muc-eip&id="+scan_id,headers=cvim_headers, session=self.session,payload="",log=self.log)
            self.log.info(response)
            if response['status'] == 'completed':
                self.log.info('Scan completed')
                isScanRunning = False
            else:
                await asyncio.sleep(5)

【问题讨论】:

    标签: python python-asyncio aiohttp


    【解决方案1】:

    您正在使用名为self.constants.cvim_headers 的东西。大概这是一个字典(包含一些默认标题)。在cvim_vlan_list 你用它来做这个

    cvim_headers = self.constants.cvim_headers
    

    然后你更新它

    cvim_container_token = response['token']
    cvim_headers['X-Auth-token'] = cvim_container_token
    

    我认为您遇到的问题只是对这里发生的事情的误解。该分配不会将self.constants.cvim_headers 的副本放入cvim_headers,而是将对self.constants.cvim_headers 引用的字典的引用放入cvim_headers。每次分配给 X-Auth-token 键时,您都会更改 cvim_headersself.constants.cvim_headers 引用的字典,覆盖与该键关联的先前值。

    为防止这种情况,您需要创建默认标题的副本并分配它。

    cvim_headers = self.constants.cvim_headers.copy()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-02
      相关资源
      最近更新 更多