python - 从 Python 3.x 中的列表中提取 IP 和端口

标签 python python-3.x

我想从返回的列表中提取 IP 和端口。我目前正在使用 str(var).replace 命令删除多余的字符。当字符串格式发生变化导致 .replace 命令出错时,这将/已经导致问题

def discover_device():
    """ This function will look for available device on the local network and extract the IP from the result"""
    discover_device = '[<Device: 192.168.222.123:8075>]' # Actually: call to broadcasting device
    device_ip = str(discover_device).replace('[<Device: ', '').replace(':8075>]', '')

所以如果出现以下情况,问题就会出现: [<Device: xxx.xxx.xxx.xxx:xxxx>]

改为: [<now_what: xxx.xxx.xxx.xxx:xxxx>]

dicovery_device()会通过和错误。

识别 ip/port 模式并提取 ip 和端口而不依赖于周围字符的完整性的最佳实践是什么?

来自:[<Device: 192.168.222.123:8075>]

对此:192.168.222.123:8075

最好是:[192.168.222.123, 8075]

考虑到点 block 内的 IP 差异和基于 16 位的最大端口号(通常冒号后 4 个整数,最多 5 个整数)

最佳答案

假设一个 IPv4 地址,尝试提取数字和关键标点符号。然后在必要时对有效结果进行切片。验证 ip 地址也可能是一种更安全的方法。

在 Python 3 中:

代码

import string
import ipaddress


def validate_port(func):
    """Return the results or raise and exception for invalid ports."""
    def wrapper(arg):
        result = func(arg)
        if len(result) == 2 and not result[-1].isdigit():
            raise ValueError("Invalid port number.")
        return result
    return wrapper


@validate_port
def discover_device(device):
    """Return a list of ip and optional port number.  Raise exception for invalid ip."""
    result = "".join(i for i in device if i in (string.digits +".:")).strip(":").split(":")

    try:
        ipaddress.ip_address(result[0])
    except ValueError as e:
        # Numbers in the device name (index 0) or invalid ip
        try:
            ipaddress.ip_address(result[1])
        except IndexError:
            raise e
        else:
            return result[1:]
    else:
        return result

演示

discover_device("[<Device: 192.168.222.123>]")
# ['192.168.222.123']

discover_device("[<Device: 192.168.222.123:8075>]")
# ['192.168.222.123', '8075']

discover_device("[<Device.34: 192.168.222.123:8080>]")
# ['192.168.222.123', '8080']

discover_device("[<Device: 192.168.222123>]")
# ValueError: '192.168.222123' does not appear to be an IPv4 or IPv6 address

discover_device("[<Device21: 192.168.222123>]")
# ValueError: '192.168.222123' does not appear to be an IPv4 or IPv6 address

discover_device("[<device.451: 192.168.222.123:80.805>]")
# ValueError: Invalid port number.

特点

  • 对周围的字符不敏感
  • IP 地址验证(非 IPv6)和异常处理
  • 防止设备名称中出现数字
  • 验证端口号(可选)

详情

通常 result 是一个包含 ip 和可选端口号的列表。但是,在设备名称中包含数字的情况下,结果的第一个索引将包含不需要的数字。以下是 result 的示例:

    # ['192.168.222.123']                                  ip   
    # ['192.168.222.123', '8075']                          ip, port
    # ['192.168.222123']                                   invalid ip
    # ['.34', '192.168.222.123', '8080']                   device #, ip, port
    # ['192.168.222.123', '80.805']                        invalid port

异常处理测试设备名称中的数字并验证第一个或第二个索引中的 ip 地址。如果未找到,则会引发异常。

虽然验证端口号不在问题范围内,但假定端口号是一个数字。 validate_port 装饰器中添加了一个简单的测试,可以根据需要应用或更新。装饰器筛选来自 discover_device() 的输出。如果端口不是纯数字,则会引发异常。参见 this post用于修改限制。参见 this blog有关 Python 装饰器的精彩教程。

选项

如果验证不是问题,下面的代码就足够了,前提是设备名称中没有“.”:

def discover_device(device):
    result = "".join(i for i in device if i in (string.digits +".:")).strip(":").split(":")
    if "." not in result[0]:
        return result[1:]
    return result

如果首选非装饰器解决方案,请定义以下函数:

def validate_port(result):
    """Return the results or raise and exception for invalid ports."""
        if len(result) == 2 and not result[-1].isdigit():
            raise ValueError("Invalid port number.")
        return result

现在将 discover_device() 的返回值传递给后一个函数,即 return validate_port(result[1:])return validate_port(result)

向@coder 提出建议。

关于python - 从 Python 3.x 中的列表中提取 IP 和端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46246615/

相关文章:

python - 子进程在完成之前终止 PowerShell 脚本

python - SSL:CERTIFICATE_VERIFY_FAILED 证书验证失败

python-3.x - 如何将 Bootstrap 验证添加到 WTForms

python - 如何防止 lambda 函数局部变量在 python 中更改?

python - 如何使用带有 urlretrieve 的进度条模块

python - 我的数据清理脚本很慢,有什么改进的想法吗?

python - Pandas 中的插值水平独立于每行

python - 为什么在 Python 的 try/except 构造中使用 else?

可用于各种 python 的 Python 扩展(jython/IronPython/等)

Python for 循环过早停止