karpierz / libpcap

Python binding for the libpcap C library.
BSD 3-Clause "New" or "Revised" License
54 stars 14 forks source link

Windows Server compatibility #7

Open pavel-kirienko opened 3 years ago

pavel-kirienko commented 3 years ago

Has the library been tested against Windows Server? Are there any major differences in DLL handling between the desktop Windows 10 and Windows Server 2019? I don't have much experience with Windows so I might be missing something obvious but my problem is that while the library seems to be working on a desktop Windows 8/10 (running via VirtualBox), on a Windows Server 2019 I consistently get this:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Python39-x64\lib\site-packages\libpcap\__init__.py", line 7, in <module>
    from ._pcap      import * ; del _pcap      # noqa
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Python39-x64\lib\site-packages\libpcap\_pcap.py", line 70, in <module>
    from ._platform import is_windows, is_linux, defined
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Python39-x64\lib\site-packages\libpcap\_platform\__init__.py", line 27, in <module>
    from ._windows import DLL_PATH, DLL, dlclose, CFUNC
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Python39-x64\lib\site-packages\libpcap\_platform\_windows\__init__.py", line 31, in <module>
    raise OSError("Cannot find wpcap.dll library") from None
OSError: Cannot find wpcap.dll library

This is reproducible with Python 3.7, 3.8, and 3.9 in a virtualized AMD64 server.

The recipe to reproduce is:

pip install libpcap
python -c "import libpcap"
pavel-kirienko commented 3 years ago

I just discovered that the problem is, apparently, related to the PATH configuration. Adding the DLL directory to PATH explicitly before loading the module fixes the problem:

set PATH=C:\Python39-x64\lib\site-packages\libpcap\_platform\_windows\x64\wpcap;%PATH%
python -c "import libpcap"  # Success
pavel-kirienko commented 3 years ago

Functional workaround:

import os
import sys
import pathlib
import importlib.util

if sys.platform.startswith('win'):
    libpcap_dir = pathlib.Path(importlib.util.find_spec('libpcap').origin).parent
    dll_path = libpcap_dir / '_platform' / '_windows' / ('x64' if sys.maxsize.bit_length() > 32 else 'x86') / 'wpcap'
    os.environ['PATH'] += os.pathsep + str(dll_path)

import libpcap

I wouldn't venture to fix it in the upstream without @karpierz 's blessing though.

karpierz commented 3 years ago

:> Has the library been tested against Windows Server? No. At all :( :> Are there any major differences in DLL handling between the desktop Windows 10 and Windows Server 2019? Should not be any difference :(