Python 导入挂钩以添加路径
Python Import Hook to Prepend Path
我正在尝试根据 QuantConnect 的目录结构修复我的“库”导入。他们组织“用户库”的方式是这样的:
假设我创建了一个名为“Project”的项目,通过 UI 选择选择了一个名为“Utilities”的库。 QC 创建以下文件夹结构:
.
├── Project
|── main.py
├── Library
├── Utilities
├── Whatever.py
然而,QC 如何导入“Utilities”库出现了问题。它通过在删除顶级目录名称的同时导入目录的所有内容来实现。您可以将结果结构视为:
.
├── Project
|── main.py
├── Whatever.py
因此,我无法再使用 from Utilities.Whatever import *
。因此,为了缓解他们平台上的这个问题,我将每个库的所有内容放入同名文件夹中。所以原来的结构现在看起来像:
.
├── Project
|── main.py
├── Library
├── Utilities
├── Utilities
├── Whatever.py
...最终结构如下:
.
├── Project
|── main.py
├── Utilities
├── Whatever.py
现在导入工作正常。只是现在它们只能通过 QC 的在线“算法实验室”按预期工作,而不是在本地!由于 QC 导入用户库的方式,我无法更改此布局,因此我需要创建一个 python 导入挂钩,它将尝试找到一个环境变量,如果未设置,则默认为不执行钩子;但是当找到时,它在非 QC 环境中被假定为 运行,并且应该在导入的第一级目录名称前加上。即,将 from Utilities.Whatever import *
翻译成 from Utilities.Utilities.Whatever import *
.
我读过很多 articles/tutorials 关于 python 的导入挂钩,但它们都提供了广泛不同的解决方案来解决我正在寻找的问题,而且我无法理解 hook 结构的内部工作原理。
我最终创建了两个名为 'Library.py' 的文件。一个是空的,放在Library/Utilities/Utilities
,另一个(不是空的)放在Library/Utilities
。所以现在,当我在 QC 环境中的任何给定脚本中键入 import Utilities.Library
时,运行 没有任何反应(应该如此),因为被引用的 Library.py 文件是空的;当它 运行s 在本地环境中时,执行以下代码:
import os
import sys
# Use env variable to ensure we only update the sys path once
env_check = 'Checked-Library-Environment'
if os.environ.get(env_check) is None:
os.environ[env_check] = 'True'
_path = None
path = os.getcwd()
target = "Library"
library = None
# Stop searching when we've reached the root
while path is not _path:
test_path = os.path.join(path, target)
if os.path.isdir(test_path):
library = test_path
break
_path = path
path = os.path.dirname(path)
# If we've found the Library directory, add its contents to the module path list
if library is not None:
for name in os.listdir(library):
path = os.path.join(library, name)
if not path in sys.path:
sys.path.append(path)
我正在尝试根据 QuantConnect 的目录结构修复我的“库”导入。他们组织“用户库”的方式是这样的:
假设我创建了一个名为“Project”的项目,通过 UI 选择选择了一个名为“Utilities”的库。 QC 创建以下文件夹结构:
.
├── Project
|── main.py
├── Library
├── Utilities
├── Whatever.py
然而,QC 如何导入“Utilities”库出现了问题。它通过在删除顶级目录名称的同时导入目录的所有内容来实现。您可以将结果结构视为:
.
├── Project
|── main.py
├── Whatever.py
因此,我无法再使用 from Utilities.Whatever import *
。因此,为了缓解他们平台上的这个问题,我将每个库的所有内容放入同名文件夹中。所以原来的结构现在看起来像:
.
├── Project
|── main.py
├── Library
├── Utilities
├── Utilities
├── Whatever.py
...最终结构如下:
.
├── Project
|── main.py
├── Utilities
├── Whatever.py
现在导入工作正常。只是现在它们只能通过 QC 的在线“算法实验室”按预期工作,而不是在本地!由于 QC 导入用户库的方式,我无法更改此布局,因此我需要创建一个 python 导入挂钩,它将尝试找到一个环境变量,如果未设置,则默认为不执行钩子;但是当找到时,它在非 QC 环境中被假定为 运行,并且应该在导入的第一级目录名称前加上。即,将 from Utilities.Whatever import *
翻译成 from Utilities.Utilities.Whatever import *
.
我读过很多 articles/tutorials 关于 python 的导入挂钩,但它们都提供了广泛不同的解决方案来解决我正在寻找的问题,而且我无法理解 hook 结构的内部工作原理。
我最终创建了两个名为 'Library.py' 的文件。一个是空的,放在Library/Utilities/Utilities
,另一个(不是空的)放在Library/Utilities
。所以现在,当我在 QC 环境中的任何给定脚本中键入 import Utilities.Library
时,运行 没有任何反应(应该如此),因为被引用的 Library.py 文件是空的;当它 运行s 在本地环境中时,执行以下代码:
import os
import sys
# Use env variable to ensure we only update the sys path once
env_check = 'Checked-Library-Environment'
if os.environ.get(env_check) is None:
os.environ[env_check] = 'True'
_path = None
path = os.getcwd()
target = "Library"
library = None
# Stop searching when we've reached the root
while path is not _path:
test_path = os.path.join(path, target)
if os.path.isdir(test_path):
library = test_path
break
_path = path
path = os.path.dirname(path)
# If we've found the Library directory, add its contents to the module path list
if library is not None:
for name in os.listdir(library):
path = os.path.join(library, name)
if not path in sys.path:
sys.path.append(path)