我想从返回的列表中提取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>]', '')
Run Code Online (Sandbox Code Playgroud)
所以如果出现问题:
[<Device: xxx.xxx.xxx.xxx:xxxx>]
改为:
[<now_what: xxx.xxx.xxx.xxx:xxxx>]
该dicovery_device()会通过和错误.
识别ip/port模式并提取ip和port而不必依赖周围字符的完整性的最佳实践是什么?
由此: [<Device: 192.168.222.123:8075>]
对此: 192.168.222.123:8075
并且最好: [192.168.222.123, 8075]
考虑点块内的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
Run Code Online (Sandbox Code Playgroud)
演示
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.
Run Code Online (Sandbox Code Playgroud)
特征
细节
通常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
Run Code Online (Sandbox Code Playgroud)
异常处理测试设备名称中的数字并验证第一个或第二个索引中的 IP 地址。如果没有找到,则会引发异常。
尽管验证端口号超出了问题的范围,但假定端口是一个数字。validate_port装饰器中添加了一个简单的测试,可以根据需要应用或更新。装饰器筛选来自 的输出discover_device()。如果端口不是纯数字,则会引发异常。请参阅此帖子以了解修改限制。有关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
Run Code Online (Sandbox Code Playgroud)
如果首选非装饰器解决方案,请定义以下函数:
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
Run Code Online (Sandbox Code Playgroud)
现在将 的返回值传递给discover_device()后一个函数,即return validate_port(result[1:])和return validate_port(result)。
关于@coder 的建议。
| 归档时间: |
|
| 查看次数: |
988 次 |
| 最近记录: |