1

语境

我有一个运行一些 Python 代码的 Pycom WiPy 板。_urequest该代码使用模块向 .NET Web API 发出 HTTP Post 请求。

问题

当发送 HTTP Post 请求时,[Errno 202] EAI_FAIL会引发异常。这种情况一个接一个地发生了好几次,因为请求在循环中每 10 秒发送一次。

代码

Wifi客户端,连接到本地wifi并获得互联网访问权限

import json
import time
from network import WLAN

# Wifi client singleton
wifiClient = None

def initWifiClient():
    global wifiClient
    wifiClient = WifiClient()

def getWifiClient():
    global wifiClient
    return wifiClient

class WifiClient:

    wifi = None
    lastWifiConnectAttempt = None

    def __init__(self):
        self.wifi = WLAN(mode=WLAN.STA)
        pass

    def connect(self):
        if not self.__readyForNewWifiConnectAttempt():
            print("Not ready yet for new WIFI connect attempt.")
            self.__printSecondsLeftToNextConnectAttempt()
            return

        print("Trying to connect WIFI.")
        try:
            self.lastWifiConnectAttempt = time.time()
            with open('wifi.json') as json_file:
                wifiJson = json.load(json_file)

                self.wifi.connect(ssid=wifiJson['ssid'], auth=(WLAN.WPA2, wifiJson['password']), timeout=30000)

                # Add connection timeout handler to prevent timeout exception crash.
                self.wifi.callback(WLAN.SMART_CONF_TIMEOUT, handler=self.__onWifiConnectTimeout)

                pass
        except Exception as e:
            self.lastWifiConnectAttempt = None
            print (e)
            pass

    def __readyForNewWifiConnectAttempt(self):
        if self.lastWifiConnectAttempt == None:
            return True
        
        return (time.time() - self.lastWifiConnectAttempt) > 42

    def __onWifiConnectTimeout(self, args):
        self.lastWifiConnectAttempt = None
        pass

    # For debugging
    def __printSecondsLeftToNextConnectAttempt(self):
        secondsLeft = 43 - (time.time() - self.lastWifiConnectAttempt)
        if secondsLeft < 0:
            secondsLeft = 0

        print("Seconds left to be ready for next WIFI connect attempt: " +  str(secondsLeft))


Web api 调用者/客户端代码,用于向 Web api 发送不同调用的帮助模块:

此 mdoule 运行后台工作循环,该循环进行 api 调用并捕获[Errno 202] EAI_FAIL异常。

from machine import Timer
from hardware import web, unit
from events import commands as cmd
from util import weblog
import ujson
import pycom
import gc
from hardware.wifi_client import getWifiClient

# globals for this file
_background_timer = None
_background_app = None



def get_client():
  client = web.Client()
  client.base_url = "..."
  # client.base_url = "..."
  return client

def send_data(): 
  print ("sending data")
  client = get_client()

  client.headers['Content-Type'] = 'application/json'

  # client.headers['Accept'] = '*/*'
  # client.headers['User-Agent'] = 'PostmanRuntime/7.28.4'
  # client.headers['Host'] = '...'
  # client.headers['Connection'] = 'keep-alive'

  p = cmd.Measure()

  data = {
    'uuid' : unit.ID,
    'value' : round(p, 1),
    'measured': "1970-01-01T00:00:00.000Z"
  }

  response = client.post('ApiMethod', data)
  print (response.text)
  pass


def background_work(o):
  global _background_app
  global wifiClient

  try:
    pycom.rgbled(0)
    gc.collect()

    mfree = gc.mem_free()

    print ("Memfree: " + str(mfree))
    if (getWifiClient().wifi.isconnected()):

      if (mfree < 1000000):
        weblog.warning("Memory low: %d", mfree)
        print("Memory low: %d", mfree)

      send_data()
    
      app = _background_app
      fetch_data(app)
      pycom.rgbled(0x002f00)
       
    else:
      pycom.rgbled(0x2F)
      print ("Not connected to WIFI")
      getWifiClient().connect()

  except Exception as e:
    pycom.rgbled(0x2f0000)
    print("send exception")
    print(e)
    
    pass
  pass

def stop_background():
  global _background_timer
  
  if _background_timer:
    _background_timer.cancel()
    _background_timer = None

  pass

def start_background(app):
  global _background_timer, _background_app

  stop_background()

  _background_app = app
  _background_timer = Timer.Alarm(background_work, s=10, periodic=True)
  pass

HTTP 客户端,对 api 进行 HTTP 调用:

import _urequest as ureq


class Client:

  def __init__(self):
    self.headers = {}
    self.base_url = ""
    pass

  ...

  def post(self, url, payload):
    print(self.base_url)
    print(self.base_url + url)
    return ureq.post(self.base_url + url, headers = self.headers, json = payload)

  ...

  def base(self, url):
    self.base_url = url

控制台输出

sending data
send exception
[Errno 202] EAI_FAIL
Memfree: 2527712
sending data
send exception
[Errno 202] EAI_FAIL
Memfree: 2527712
sending data

问题

为什么会[Errno 202] EAI_FAIL抛出异常?

谢谢!

4

1 回答 1

0

看起来它与论坛帖子的答案中所述的 DNS 有关:

EAI_FAIL 与无法解析 DNS 有关。

看起来它是一个植根于getaddrinfo()函数的特定于 Pycom 的错误代码(另一个论坛帖子)。您还会发现它在LTE 文档中被简要提及(向下滚动到“Pycom simcards”部分)

我猜这会在你设置时被调用client.base_url?TBH,我不认识您从 Pycom 文档中导入的一些内容。

于 2022-01-14T17:51:40.380 回答