Python中的包模組引用成員的方法

華科雲商小雪發表於2024-02-07

在Python中,包(package)和模組(module)是組織和管理程式碼的重要方式。將程式碼分成不同的模組或包可以更好地組織程式碼結構,使程式碼更易於維護和管理。說的通俗點,就是將程式碼整理成一塊一塊,然後使用時候相互拼接完成就可以使用,這樣的好處是可用性高而且非常方便維護,尤其是在選擇大型爬蟲專案的來說非常有用。

1、問題背景

在Python中, 當我們擁有一個具有多個子模組的包時,可能會遇到這樣的問題:希望在包的外部引用子模組中的成員,但是並不希望在包的名稱空間中看到子模組本身。這可能會導致程式碼的可讀性和維護性降低。

舉個例子,假設我們有一個名為 package 的包,其中包含 foo_module.py example_module.py 兩個子模組。


test.
py

package /
    __init__. py
    foo_module. py
    example_module. py

test.py 中,我想引用 package 中的成員,但並不希望看到 foo_module example_module 這兩個子模組本身。我希望 package 模組看起來像這樣:


>>> 
vars(
package)

mapping_proxy({ foo: < function foo at 0 x…}, { example: < function example at 0 x…})

也就是說,我希望 package 中的所有子模組的成員都在 package 的名稱空間中,而子模組本身不在名稱空間中。

2、解決方案

有多種方法可以解決這個問題,其中一種方法是使用 from module import name 形式的匯入方式。對於 example_module.py ,我們可以這樣匯入:

from package.foo_module import foo

對於 __init__.py ,我們可以這樣匯入:


from 
package.
foo_module 
import 
foo

from package. example_module import example

__all__ = [ foo, example] # not strictly necessary, but makes clear what is public

test.py 中,我們可以這樣匯入:

from package import example

注意,這種方法只適用於在包層級執行 test.py ,否則需要確保包含 package 的資料夾在Python模組搜尋路徑中。

另一種方法是使用動態匯入。這涉及在 __init__.py 檔案中動態匯入包中的所有模組,並將其成員新增到包的名稱空間中。以下是一個示例:


def 
_import_all_modules():

    """ Dynamically imports all modules in this package. """
    import traceback
    import os
    global __all__
    __all__ = []
    globals_, locals_ = globals(), locals()

    # Dynamically import all the package modules in this file's directory.
    for filename in os. listdir( __name__):
        # Process all python files in directory that don't start
        # with underscore (which also prevents this module from
        # importing itself).
        if filename[ 0] != '_' and filename. split( '.')[ - 1] in ( 'py', 'pyw'):
            modulename = filename. split( '.')[ 0]   # Filename sans extension.
            package_module = '.'. join([ __name__, modulename])
            try:
                module = __import__( package_module, globals_, locals_, [ modulename])
            except:
                traceback. print_exc()
                raise
            for name in module. __dict__:
                if not name. startswith( '_'):
                    globals_[ name] = module. __dict__[ name]
                    __all__. append( name)

_import_all_modules()

test.py 中,我們可以這樣匯入:

from package import *

這種方法更加動態,不需要在 __init__.py 檔案中硬編碼包模組名稱。需要動態匯入新模組時,它將自動匯入它們,而不再嘗試匯入從目錄中刪除的模組。

透過使用包和模組,程式碼結構更清晰,邏輯更明確,易於理解和維護,這樣極大的減少我們的維護成本,而且非常方便協作開發,透過小事情可以讓我獲得更多的收益。今天的內容就這些了,如果有更多的疑問,可以評論區留言探討。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70034537/viewspace-3006524/,如需轉載,請註明出處,否則將追究法律責任。

相關文章