开发者社区 问答 正文

使用pcap模板时的ipv6Packet错误

尝试使用python中的Kaitai Struct读取pcap。

我已经从该js pcap.ksy 文
件创建了python 文件

$ ./bin/kaitai-struct-compiler -t python  --outdir xx formats/network/pcap.ksy 
$ ls xx
ethernet_frame.py  ipv6_packet.py  __pycache__
icmp_packet.py     packet_ppi.py   tcp_segment.py
ipv4_packet.py     pcap.py         udp_datagram.py

PYTHONPATH设置为xx目录。现在,如果我运行一个简单的单行脚本来检查是否可以加载模块

from pcap import Pcap

我得到这个错误

$ python3 try.py 
Traceback (most recent call last):
  File "try.py", line 1, in <module>
    from pcap import Pcap
  File "/spare/tmp/scratch/kaitai-struct-compiler-0.8/xx/pcap.py", line 11, in <module>
    from packet_ppi import PacketPpi
  File "/spare/tmp/scratch/kaitai-struct-compiler-0.8/xx/packet_ppi.py", line 11, in <module>
    from ethernet_frame import EthernetFrame
  File "/spare/tmp/scratch/kaitai-struct-compiler-0.8/xx/ethernet_frame.py", line 11, in <module>
    from ipv6_packet import Ipv6Packet
  File "/spare/tmp/scratch/kaitai-struct-compiler-0.8/xx/ipv6_packet.py", line 12, in <module>
    from ipv4_packet import Ipv4Packet
  File "/spare/tmp/scratch/kaitai-struct-compiler-0.8/xx/ipv4_packet.py", line 13, in <module>
    from ipv6_packet import Ipv6Packet
ImportError: cannot import name 'Ipv6Packet'

我的理解是,python路径尚可,并且python模块正在从pacp到以太网,ipv6到ipv4的整个链中运行。然后,ipv4尝试再次加载ipv6,脚本崩溃了。

我认为代码正在触发导入循环。

有人知道我在做什么错吗?

展开
收起
几许相思几点泪 2019-12-10 19:52:21 913 分享 版权
阿里云 AI 助理回答

你遇到的问题确实是由导入循环引起的。在Python中,当两个或多个模块相互尝试导入对方时,就会发生导入循环。从你的错误信息来看,ipv4_packet.py试图导入ipv6_packet.py,而后者又反过来尝试导入ipv4_packet.py,形成了一个循环依赖。

解决这个问题的一种方法是使用Python中的import语句的延迟特性,即只在真正需要使用到该类或函数时才进行导入。你可以通过以下方式修改代码来避免直接在模块顶部导入:

修改前的代码示例 (问题所在)

ipv4_packet.py

from ipv6_packet import Ipv6Packet
# ... 其他代码

ipv6_packet.py

from ipv4_packet import Ipv4Packet
# ... 其他代码

修改后的代码示例

将直接导入改为在具体使用时导入:

ipv4_packet.py

# ... 其他代码直到实际需要使用Ipv6Packet的地方
class SomeClassInIpv4:
    def some_method(self):
        from ipv6_packet import Ipv6Packet
        # 现在才真正需要Ipv6Packet
        # 使用Ipv6Packet...

ipv6_packet.py

# ... 其他代码直到实际需要使用Ipv4Packet的地方
class SomeClassInIpv6:
    def some_method(self):
        from ipv4_packet import Ipv4Packet
        # 现在才真正需要Ipv4Packet
        # 使用Ipv4Packet...

这样修改后,每个模块在被其他模块导入时不会立即尝试导入另一个可能还在初始化过程中的模块,从而打破了循环依赖。

另外,如果你发现某些类或函数实际上并不需要直接导入另一个模块的所有内容,而是只需要其中的一部分,可以考虑仅导入所需的那部分(例如,特定的类或函数),这也能帮助减少潜在的循环依赖问题。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答地址: