我正在尋找一種簡單而快速的方法來查找軟件包的根目錄以及完整模塊名稱從.py文件的路徑。從.py文件中獲取軟件包根目錄和完整模塊名稱以便導入
我希望用戶選擇一個.py並導入它而不會中斷。如果模塊是包的一部分,則導入模塊可能會中斷。因此,我想自動將包的根目錄所在的目錄附加到sys.path(如果尚未存在),然後使用完整的模塊名稱導入模塊。
我沒有從同一目錄或腳本中的任何地方運行,所以我不能使用__file__
以及那種東西。另外我還沒有導入模塊,所以我不能(據我所知)檢查模塊對象,因爲沒有。
這是一個工作版本,但我很想找到更簡單/更快的解決方案。
def splitPathFull(path):
folders=[]
while 1:
path,folder=os.path.split(path)
if folder!="":
folders.append(folder)
else:
if path!="":
folders.append(path)
break
folders.reverse()
return folders
def getPackageRootAndModuleNameFromFilePath(filePath):
"""
It recursively looks up until it finds a folder without __init__.py and uses that as the root of the package
the root of the package.
"""
folder = os.path.dirname(filePath)
if not os.path.exists(folder):
raise RuntimeError("Location does not exist: {0}".format(folder))
if not filePath.endswith(".py"):
return None
moduleName = os.path.splitext(os.path.basename(filePath))[0] # filename without extension
#
# If there's a __init__.py in the folder:
# Find the root module folder by recursively going up until there's no more __init__.py
# Else:
# It's a standalone module/python script.
#
foundScriptRoot = False
fullModuleName = None
rootPackagePath = None
if not os.path.exists(os.path.join(folder, "__init__.py")):
rootPackagePath = folder
fullModuleName = moduleName
foundScriptRoot = True
# It's not in a Python package but a seperate ".py" script
# Thus append it's directory name to sys path (if not in there) and import the .py as a module
else:
startFolder = folder
moduleList = []
if moduleName != "__init__":
moduleList.append(moduleName)
amountUp = 0
while os.path.exists(folder) and foundScriptRoot == False:
moduleList.append (os.path.basename(folder))
folder = os.path.dirname(folder)
amountUp += 1
if not os.path.exists(os.path.join(folder, "__init__.py")):
foundScriptRoot = True
splitPath = splitPathFull(startFolder)
rootPackagePath = os.path.join(*splitPath[:-amountUp])
moduleList.reverse()
fullModuleName = ".".join(moduleList)
if fullModuleName == None or rootPackagePath == None or foundScriptRoot == False:
raise RuntimeError("Couldn't resolve python package root python path and full module name for: {0}".format(filePath))
return [rootPackagePath, fullModuleName]
def importModuleFromFilepath(filePath, reloadModule=True):
"""
Imports a module by it's filePath.
It adds the root folder to sys.path if it's not already in there.
Then it imports the module with the full package/module name and returns the imported module as object.
"""
rootPythonPath, fullModuleName = getPackageRootAndModuleNameFromFilePath(filePath)
# Append rootPythonPath to sys.path if not in sys.path
if rootPythonPath not in sys.path:
sys.path.append(rootPythonPath)
# Import full (module.module.package) name
mod = __import__(fullModuleName, {}, {}, [fullModuleName])
if reloadModule:
reload(mod)
return mod
只是一個問題;爲什麼?什麼是最終目標?這只是一個excersize? – placeybordeaux 2013-02-12 15:36:20
我正在嘗試創建一個允許在程序的python包之外設計插件/附加類的API。這將用於創建將定義新對象類型的新類。我希望用戶說'將這個文件/文件夾包含在對象類型清單中'。然而,這個文件/文件夾可能是另一個項目/軟件包的一部分,當它自行導入時可能會破壞一些代碼。 (對吧?)我需要導入文件來獲取類,但也檢查它是否是一個有效的新類。最終導致類似。進口包; package.addPluginPath(「filepath」) – 2013-02-12 15:41:59
@RoyNieterau你應該只需要'嘗試:除了:'加載模塊來處理無效導入的情況。我不確定任何插件架構是否100%安全...... Python中有太多內省工具可以讓任何插件混淆正在運行的解釋器。 – 2013-02-12 15:47:46