簡體   English   中英

如何判斷一個包/模塊是否是 Python 標准庫的一部分? 沒有第三方庫

[英]How can I tell if a package/module is part of Python's std library? without a 3rd party library

我想查看/限制應用程序中的依賴項,並且我想忽略給定 Python 版本的標准庫中已經包含的所有內容。 什么是簡單的 Pythonic 方式來做到這一點?

我已經做了一些工作,但由於這似乎是一個相當基本的問題,我想知道是否有更好的方法。 而且我的解決方案現在看起來很危險地依賴於平台(我在 macos 上,它可能適用於 Linux,懷疑它是否適用於 Windows)。

基本上,我查看已知 stdlib 模塊所在的目錄,然后從中獲取 python 文件目錄。

到目前為止我所擁有的

#parent directory for the `os` module.
pa_lib_builtins = Path(os.__file__).parent
s_stdlib = set()

for pa_py in pa_lib_builtins.glob("*"):

    #skip some directories
    if pa_py.name in {"site-packages", "lib-dynload"}:
        continue

    #add modules/packages
    if pa_py.suffix == ".py":
        #a direct module, add it.
        s_stdlib.add(pa_py.stem)
    else:
        #it's a package, add it
        if pa_py.is_dir():
            s_stdlib.add(pa_py.name)

#looks too operating-system dependent... add the stuff in lib-dynload
pa_lib_dynload = pa_lib_builtins / "lib-dynload"
for pa in pa_lib_dynload.glob("*"):
    s_stdlib.add(pa_py.stem.split(".")[0])

#add stuff that I can't find on the file system but is registered as built-in
#this brings in `sys`, for example.
for name in sys.builtin_module_names:
    s_stdlib.add(name)

macos 上lib-dynload的內容(我只抓住第一個.的左側)。

.
..
_asyncio.cpython-36m-darwin.so
_bisect.cpython-36m-darwin.so
_blake2.cpython-36m-darwin.so

我有更好的方法嗎? 請注意,我並不太擔心誤報。 例如,將__pycache__視為一個模塊並沒有真正的傷害,因為我不需要擔心任何import __pycache__

這主要通過在運行時自省文件系統來解決問題。 與文檔解析不同,它對當前操作系統上實際安裝的內容很敏感。 它也可以在沒有互聯網訪問的情況下工作。

那么 - 從比較 3.6 的https://github.com/jackmaney/python-stdlib-list

  • 我的 Mac 上沒有msilibmsvcr
  • 拿起posixpath

稍后我將針對 Windows 和 Linux 運行此程序並根據需要進行更新,但我預計它應該可以輕松工作。


def get_stdlib_names(try_import=False):
    """ 
    get stdlib module/package names 
    by globbing file system
    """

    import pathlib
    Path = pathlib.Path

    pa_dyn_name = os_specific = pa_dyn = None
    s_stdlib0 = set()

    try:
        # Unix services
        import syslog as os_specific
    except ModuleNotFoundError:
        try:
            # Windows services
            import msilib as os_specific
        except ModuleNotFoundError:
            pass

    # parent directory for `pathlib`  itself
    pa_stdlib = Path(pathlib.__file__).parent

    # OS-dependent/dynamic libraries
    if os_specific:
        pa_dyn = Path(os_specific.__file__).parent
        pa_dyn_name = pa_dyn.name

    for pa_py in pa_stdlib.glob("*"):

        # skip directories we don't want
        if pa_py.name in {"site-packages", pa_dyn_name, "test"}:
            continue

        # add modules (*.py)/packages (directories
        if pa_py.suffix == ".py":
            s_stdlib0.add(pa_py.stem)
        else:
            if pa_py.is_dir():
                s_stdlib0.add(pa_py.name)

    # load dynamic libraries
    if os_specific:
        # consider qualifying glob with `.dll`/`.so` extension
        for pa in pa_dyn.glob("*"):
            name = pa.stem.split(".")[0]
            s_stdlib0.add(name)

    # add stuff not on the file system, like `sys`
    for name in sys.builtin_module_names:
        s_stdlib0.add(name)

    # skip `_` aliases for modules:
    #  .../lib/python3.6/asyncio/__init__.py
    #  .../lib/python3.6/lib-dynload/_asyncio.cpython-36m-darwin.so
    s_stdlib0 = {
        name
        for name in s_stdlib0
        if (not name.startswith("_"))
        # special cases
        or name in ("__future__ _thread _dummy_thread".split())
    }

    s_stdlib0.add("__main__")

    # do we want to check if we can import it?
    if not try_import:
        return s_stdlib0

    s_stdlib = set()

    for name in s_stdlib0:

        # side effects/won't import
        if name in ("antigravity", "this", "__main__"):
            s_stdlib.add(name)
            continue
        try:
            importlib.import_module(name)
            s_stdlib.add(name)
        except ModuleNotFoundError as e:
            pass

    return s_stdlib

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM