无法在Python中导入libarchive-c:FileNotFoundError

问题描述 投票:0回答:1

我试图有选择地自动从许多 7zip 文件中提取文件,通常的

patool
pyunpack
等不允许选择要提取的文件。
py7zr
似乎提供了该功能,但我发现提取单个文件效率极低。

我在手动制作此 Google 查询后发现

libarchive-c

https://www.google.com/search?q=%22python%22+%227z%22+-patool+-pyunpack+-py7zr&tbs=li:1

在垃圾中筛选,它仍然会返回。

我安装了libarchive

此版本
,我在此处下载了适用于Windows 10 x64的二进制文件。

我将libarchive包中的文件解压到D:\Programs\libarchive。

一开始我什至无法导入

libarchive
:

In [20]: import libarchive
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [20], in <cell line: 1>()
----> 1 import libarchive

File C:\Program Files\Python310\lib\site-packages\libarchive\__init__.py:1, in <module>
----> 1 from .entry import ArchiveEntry
      2 from .exception import ArchiveError
      3 from .extract import extract_fd, extract_file, extract_memory

File C:\Program Files\Python310\lib\site-packages\libarchive\entry.py:6, in <module>
      3 from enum import IntEnum
      4 import math
----> 6 from . import ffi
      9 class FileType(IntEnum):
     10     NAMED_PIPE     = AE_IFIFO  = 0o010000  # noqa: E221

File C:\Program Files\Python310\lib\site-packages\libarchive\ffi.py:26, in <module>
     23 page_size = mmap.PAGESIZE
     25 libarchive_path = os.environ.get('LIBARCHIVE') or find_library('archive')
---> 26 libarchive = ctypes.cdll.LoadLibrary(libarchive_path)
     29 # Constants
     31 ARCHIVE_EOF = 1       # Found end of archive.

File C:\Program Files\Python310\lib\ctypes\__init__.py:452, in LibraryLoader.LoadLibrary(self, name)
    451 def LoadLibrary(self, name):
--> 452     return self._dlltype(name)

File C:\Program Files\Python310\lib\ctypes\__init__.py:364, in CDLL.__init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    362 import nt
    363 mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
--> 364 if '/' in name or '\\' in name:
    365     self._name = nt._getfullpathname(self._name)
    366     mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR

TypeError: argument of type 'NoneType' is not iterable

找出问题所在非常容易,至少对我来说是这样。正是因为这一行:

libarchive_path = os.environ.get('LIBARCHIVE') or find_library('archive')

它会搜索环境变量来归档libarchive库的路径,但我下载的是.zip包而不是安装程序,它没有设置环境变量,所以第一个命令返回

None
。当然这意味着第二个命令也失败了。

所以我必须手动提供正确的路径。它没有详细记录,至少我还没有找到它,但紧接在它下面的行是:

libarchive = ctypes.cdll.LoadLibrary(libarchive_path)

这意味着该路径应该是.dll路径,所以我将其更改为:

libarchive_path = "D:/Programs/libarchive/bin/archive.dll"

但我还是无法导入

libarchive
:

FileNotFoundError: Could not find module 'D:\Programs\libarchive\bin\archive.dll' (or one of its dependencies). Try using the full path with constructor syntax.

我搜索了这个错误,发现了很多不相关的信息。我发现很多类似的帖子:Can't import dll module in Python

但是它们都没有帮助,因为我提供了绝对路径,而它们都在处理相对路径。

所以消息的第一部分是

False
,一定不是这样的,文件一定是确实找到了,或者库代码中有严重的错误,或者Python实现......

难道这个.dll依赖的目录下还存在其他.dll文件?

我已尝试以下命令,但没有解决问题:

os.chdir("D:/Programs/libarchive/bin")
os.add_dll_directory("D:/Programs/libarchive/bin")

不,该目录中只有一个 .dll:

PS D:\Programs\libarchive\bin> (gci).fullname
D:\Programs\libarchive\bin\archive.dll
D:\Programs\libarchive\bin\bsdcat.exe
D:\Programs\libarchive\bin\bsdcpio.exe
D:\Programs\libarchive\bin\bsdtar.exe
PS D:\Programs\libarchive\bin>

那么我该如何解决这个问题?


更新

我使用这个程序来查找任何可执行文件导入的.dll文件:

import json
import os
import subprocess

def get_dependencies(exe):
    return [
        i["Name"] 
        for i in 
        json.loads(
            subprocess.run(
                ["D:/Programs/Dependencies_x64_Release/Dependencies.exe", "-json", "-imports", exe],
                capture_output=True,
                text=True
            ).stdout
        )["Imports"]
    ]


dependencies = get_dependencies("D:/Programs/libarchive/bin/archive.dll")

.dll 文件导入以下文件:

['bcrypt.dll',
 'libcrypto-1_1-x64.dll',
 'KERNEL32.dll',
 'VCRUNTIME140.dll',
 'api-ms-win-crt-runtime-l1-1-0.dll',
 'api-ms-win-crt-heap-l1-1-0.dll',
 'api-ms-win-crt-string-l1-1-0.dll',
 'api-ms-win-crt-time-l1-1-0.dll',
 'api-ms-win-crt-utility-l1-1-0.dll',
 'api-ms-win-crt-stdio-l1-1-0.dll',
 'api-ms-win-crt-convert-l1-1-0.dll',
 'api-ms-win-crt-locale-l1-1-0.dll',
 'api-ms-win-crt-environment-l1-1-0.dll',
 'api-ms-win-crt-filesystem-l1-1-0.dll']

我试图找到哪些不存在:

for dll in dependencies:
    if not os.path.isfile("C:/Windows/System32/" + dll):
        print(dll)
libcrypto-1_1-x64.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll

看来我需要下载

libcrypto-1_1-x64.dll
,但是其他文件是什么?它们似乎不太可能丢失,但它们不在 System32 文件夹中。

python ctypes libarchive
1个回答
0
投票

感谢这个评论我能够解决这个问题。

所以我使用这个程序来查找任何可执行文件的依赖关系,我使用以下代码来过滤掉不必要的信息:

import json
import os
import subprocess

def get_dependencies(exe):
    return [
        i["Name"] 
        for i in 
        json.loads(
            subprocess.run(
                ["D:/Programs/Dependencies_x64_Release/Dependencies.exe", "-json", "-imports", exe],
                capture_output=True,
                text=True
            ).stdout
        )["Imports"]
    ]


dependencies = get_dependencies("D:/Programs/libarchive/bin/archive.dll")

我得到了这个:

['bcrypt.dll',
 'libcrypto-1_1-x64.dll',
 'KERNEL32.dll',
 'VCRUNTIME140.dll',
 'api-ms-win-crt-runtime-l1-1-0.dll',
 'api-ms-win-crt-heap-l1-1-0.dll',
 'api-ms-win-crt-string-l1-1-0.dll',
 'api-ms-win-crt-time-l1-1-0.dll',
 'api-ms-win-crt-utility-l1-1-0.dll',
 'api-ms-win-crt-stdio-l1-1-0.dll',
 'api-ms-win-crt-convert-l1-1-0.dll',
 'api-ms-win-crt-locale-l1-1-0.dll',
 'api-ms-win-crt-environment-l1-1-0.dll',
 'api-ms-win-crt-filesystem-l1-1-0.dll']

我很快就确定了

libcrypto-1_1-x64.dll
丢失了,所以我从这里下载了它,我提取了存档并将.dll复制粘贴到C:\Windows\System32目录中,问题就解决了。

© www.soinside.com 2019 - 2024. All rights reserved.