2013-10-10 76 views
0

我想將一個external包添加到我的程序中,該程序應該包括它使用的所有配方和第三方包。我不想強迫任何人(包括我自己)安裝這些軟件包,更不用說版本不兼容。我只是 想把它們放到自己的子文件夾中並使用它們。他們, 當然來自各種來源。輕鬆導入所有第三方包和腳本作爲公共包?

的文件夾結構應該是這樣的:

| main.py 
|---[external] 
    |---[networkx] 
    | | ... 
    |---[xlrd] 
    | | ... 
    | __init__.py 
    | recipe1.py 
    | recipe2.py 

我想達到的包裝和配方,在我的程序通過以下方式:

import external 
import external.xlrd 
from external import networkx as nx 
import external.recipe1 
from external import recipe2 as magic 
from external import * 

任何包但是可能包含絕對導入其中可導致ImportError假設external具有空的__init__.py

>>> import external.networkx 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File ".\external\networkx\__init__.py", line 46, in <module> 
    from networkx import release 
ImportError: No module named 'networkx' 

有沒有簡單的方法來製作這樣的外部包裝?

回答

0

我做了這個功能。所有你需要做的就是把此行到外部文件夾的__init__.py

__all__ = import_all(__path__) 

此功能一般可以用它來導入所有的子模塊,即使它們是嵌套的,只是把這個所有涉及到的__init__.py

如果你知道這個問題更清潔的解決方案,請與我們分享!我不會接受我自己的答案。

from os import listdir 
from os.path import abspath, basename, exists, isdir, join, \ 
    relpath, sep, splitext 
from sys import path 

def import_all(path__here): 
    """Imports all subpackages and submodules, excluding .py 
files starting with an underscore. The directories have to 
have an __init__.py to get imported. 

Add this line to the __init__.py: 
    __all__ = import_all(__path__)""" 
    result, packagepath = [], relpath(path__here[0]) 
    for e in listdir(packagepath): 
     mod_path = join(packagepath, e) 
     mod_name = splitext(basename(e))[0] 
     file_to_import = (e.endswith(".py") 
      and not mod_name.startswith("_")) 
     dir_to_import = (isdir(mod_path) 
      and exists(join(mod_path, "__init__.py"))) 
     if not file_to_import and not dir_to_import: 
      continue 
     im_str = ".".join(mod_path.split(sep)[:-1] + [mod_name]) 
     try: 
      __import__(im_str) 
     except ImportError as err: 
      # In case of a subpackage countains absolute imports 
      # assuming it is in the root, we put it into the 
      # system path and try again. 
      if abspath(packagepath) not in path: 
       path.insert(0, abspath(packagepath)) 
       __import__(im_str) 
      else: 
       raise err from None 
     result.append(mod_name) 
    return result