【问题标题】:Exception handling with IP Address ModuleIP 地址模块的异常处理
【发布时间】:2017-06-15 18:46:05
【问题描述】:

我不是专业的软件工程师(网络安全工程师),并且正在学习更多自动化技术和编码。我确定我只是在我的代码中遗漏了一些非常明显的东西,我们将不胜感激。

我正在运行一个输入脚本,要求用户将 IP 地址以 CIDR 或 IPv4/v6 格式的主机 IP 输入到输入框中(在 Tkinter 中)。我有两个单独的编码脚本来执行这些功能(CIDR 和主机 IP)。我正在尝试将代码组合在一起,因此只需要运行一个应用程序。

使用 ipaddress 模块时,如果输入的格式不正确(使用 ip_address(用于主机地址)或 ip_network(用于 CIDR 地址)),则会抛出 Value 错误。这就是我想要的,因为我正在处理这些异常。

问题是我需要将 CIDR 和 IP 主机都添加到单独的 REST API 调用列表中(因为需要不同的调用格式)。当我下面的代码处理时,如果文本框中的条目是 CIDR 格式,它将抛出 Value 错误(因为 IP Host 是第一个语句,这就是它抛出错误的原因)。

我已经能够让它同时处理 ipaddress 输入,用下面的代码代替第二个 elif 语句(第一个只是空输入的故障保护):

if self.ip == str(ipaddress.ip_network(self.e1.get())) or self.ip == str(ipaddress.ip_address(self.e1.get())):

上述语句的问题是我无法破译 self.ip 并将其附加到适当的列表(一个用于 CIDR,一个用于 IP 主机)。

如前所述,我的主代码的主要问题是,如果输入是 CIDR,它会抛出 value 错误,因为第二个 elif 块将 ipaddress.ip_address 作为第一个输入,并且一旦遇到错误它不会继续代码。

也许这是一个结构问题,或者我没有问正确的问题...但是我的代码中的任何帮助都允许某人输入主机 IP 地址或 CIDR 格式子网,并且代码抛出一个值错误如果这两个都没有输入。以及将每个附加到其适当的列表中,将不胜感激。

主代码(仅供参考:e1 变量是输入文本框):

  def add_ip(self):
    self.hostiplist = []
    self.cidriplist = []
    try:
      if not self.e1.get():# empty! (empty string is false value)
        messagebox.showerror(title='Error', message='Ooops, Please enter an acceptible host or network IP Address.')
        self.e1.delete(0,END)
      elif self.e1.get() == " ":
        messagebox.showerror(title='Error', message='Ooops, Please enter an acceptible host or network IP Address.')
        self.e1.delete(0,END)
      else:
        self.ip = self.e1.get()
        if self.ip == str(ipaddress.ip_address(self.e1.get())):
          self.hostiplist.append(self.ip)
          print("IP Host staged for deployment: %s" % (self.ip))
          print("")
          self.e1.delete(0,END)
        elif self.ip == str(ipaddress.ip_network(self.e1.get())):
          self.cidriplist.append(self.ip)
          print("IP Network staged for deployment: %s" % (self.ip))
          print("")
          self.e1.delete(0,END)
        else:
          print("Didn't enter valid entry")

    except ValueError as e:
      messagebox.showerror(title='Error', message='Ooops,' + str(e) + '.' + ' Please enter an acceptible host or network IP Address.')
      self.e1.delete(0,END)
      return 'Value'    
    except TypeError:
      messagebox.showerror(title='Error', message='Ooops,' + str(e) + '.' + ' Please enter an acceptible host or network IP Address.')
      self.e1.delete(0,END)
      return 'Type'

这是我的单个函数脚本,它适用于错误处理(如果输入了除 CIDR 格式之外的任何内容,您将收到值错误):

def add_ip_network():
   #IPv4 & v6 Address Handling.  Nothing but those formats can be entered.
  try:
    ip = ipaddress.ip_network(e1.get())
    nonsubnethostsList.append(ip)
    print("IP Network staged for deployment: %s" % (ip))
    print("")
    e1.delete(0,END)
  except ValueError:
    print('Incorrect entry, please use IPv4 or IPv6 CIDR Formats')
    e1.delete(0,END)
    return 'Value'
  except TypeError:
    print('Incorrect entry, please use IPv4 or IPv6 CIDR Formats')
    e1.delete(0,END)
    return 'Type'

问候,

编辑:
我还尝试调整我的主代码以匹配我工作的单一格式脚本。 从此:

if self.ip == str(ipaddress.ip_address(self.e1.get()))

到这里:

ip = ipaddress.ip_network(e1.get())

它给了我相同的值错误,所以我尝试将字符串与 If 语句进行比较。

【问题讨论】:

    标签: python-3.x rest api ip-address


    【解决方案1】:

    我在 Reddit/Python 上从用户 Dagger0 那里得到了上述问题的答案(谢谢!)。

    所以基本上你需要做的是...找出一个字符串是一个 IP 还是一个带有 CIDR 掩码的网络?好像你可以只测试“/”。

    # Presumably set these in __init__ or something, you don't
    # want to be clearing them each time you add an entry.
    self.hostiplist = []
    self.cidriplist = []
    
    def add_ip(self):
        input = self.e1.get()
        try:
            if "/" in input:
                ip = ipaddress.ip_address(input)
                # Append to self.hostiplist.
            else:
                network = ipaddress.ip_network(input)
                # Append to self.cidriplist.
        except (ValueError, TypeError) as e:
            msg = 'Ooops: %s. Please enter an acceptable host or network IP Address.' % str(e)
            messagebox.showerror(title='Error', message=msg)
            self.e1.delete(0, END)
            raise e # If you want the caller to get an exception too. Although in that case maybe the
                    # whole try/except business should be in the caller, like in the bottom code block.
    

    (完全未经测试。)

    我删除了对 "" 和 " " 的检查,因为 ipaddress.ip_address() 无论如何都可能对这些输入抛出异常,所以我们不妨只使用一个异常处理程序。我不知道这是否真的是它的行为方式。

    您的一般问题是在 ipaddress.ip_address() 抛出后您不必费心尝试 ipaddress.ip_network() (但在这种情况下,碰巧有另一种区分两个输入的方法)。

    你也可以这样做:

    try:
        ipaddress.ip_address(input)
        # It's an IP.
    except (ValueError, TypeError):
        ipaddress.ip_network(input)
        # It's a network.
    

    也许会导致这样的代码结构:

    def add_ip(self, input):
        try:
            ipaddress.ip_address(input)
            # It's an IP.
        except (ValueError, TypeError):
            ipaddress.ip_network(input)
            # It's a network.
    
    def on_button_press(self):
        try:
            self.add_ip(self.e1.get())
        except (ValueError, TypeError):
            # Neither.
            self.e1.delete(0, END)
    

    我测试了底部的两个功能,它们完美无缺!希望这对其他人有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-16
      • 2012-11-04
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      相关资源
      最近更新 更多