ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hydra 1.1 到 1.2 迁移指南:`hydra.job.chdir` 与作业运行时工作目录行为变更

Hydra 1.1 到 1.2 迁移指南:`hydra.job.chdir` 与作业运行时工作目录行为变更 Hydra 1.1 到 1.2 迁移指南hydra.job.chdir与作业运行时工作目录行为变更【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra本指南面向从 Hydra 1.1 升级到 1.2 及更高版本的开发者系统讲解作业Job运行时工作目录working directory行为的重大变更Hydra 1.2 新增了hydra.job.chdir配置项并将其默认值设为False。读完本文你将掌握该配置项的作用机制、新旧行为差异、恢复旧行为的迁移方法以及如何在chdir开启后仍然安全访问原始工作目录确保升级过程平滑无痛。变更背景Hydra 1.1 及更早版本的行为在 Hydra 1.1 及更早版本中Hydra 在每次运行应用前都会自动执行os.chdir将 Python 进程的当前工作目录切换到本次运行专属的输出目录output directory中。输出目录按hydra.run.dir单次运行或hydra.sweep.dir/hydra.sweep.subdir多任务 sweep的模板自动生成其实际路径可在运行时通过hydra.runtime.output_dir获取。这种自动切目录的行为在方便保存应用产物如数据库 dump、模型权重的同时也给不少用户带来了困扰应用代码中任何依赖相对路径的文件访问都会因为工作目录被切换而指向输出目录一旦应用需要访问启动目录下的资源如预训练的权重文件、数据目录就会出现找不到文件的意外。这正是 Hydra 1.2 调整该行为的直接动因。Hydra 1.2 的核心变更新增hydra.job.chdir默认FalseHydra 1.2 引入了配置项hydra.job.chdir用于显式控制 Hydra 是否在调用用户装饰的主函数之前将 Python 运行时工作目录切换到作业输出目录。变更要点hydra.job.chdir的当前默认值为False。升级到 Hydra 1.2 后工作目录默认不再被切换到输出目录应用将在启动时的原始工作目录中运行。如果你希望保留 Hydra 1.1 的旧行为即启动后工作目录自动变为输出目录必须为你的应用显式设置hydra.job.chdirTrueHydra 不会替你做出这个决定。配置项的权威定义hydra.job.chdir属于hydra.job配置组其类型为布尔值bool。在仓库中该配置项定义于 hydra/conf/init.py 的JobConf结构化配置Structured Config中# job runtime information will be populated here dataclass class JobConf: # Job name, populated automatically unless specified by the user (in config or cli) name: str MISSING # Change current working dir to the output dir. chdir: bool False # Deprecated. Use the hydra_override_dirname resolver instead. override_dirname: str ${hydra_override_dirname:} # Job ID in underlying scheduling system id: str MISSING # Job number if job is a part of a sweep num: int MISSING # The config name used by the job config_name: Optional[str] MISSING ...从源码结构可以确认chdir字段的默认值在当前仓库中即为Falsechdir: bool False与迁移文档的说明完全一致。JobConf还包含name、id、num、config_name、env_set、env_copy等运行时字段其中env_set/env_copy用于在远程或本地运行中管理环境变量完整的字段说明可参阅 Job Configuration。新旧行为对比一个直观的示例以下示例改编自官方教程 Output/Working directory用于直观展示 1.2 前后行为差异。应用代码import os from omegaconf import DictConfig import hydra hydra.main() def my_app(_cfg: DictConfig) - None: print(fWorking directory : {os.getcwd()}) print(fOutput directory : {hydra.core.hydra_config.HydraConfig.get().runtime.output_dir})运行结果对比# check current working dir $ pwd /home/jasha/dev/hydra # for Hydra 1.2, working dir remains unchanged by default $ python my_app.py Working directory : /home/jasha/dev/hydra Output directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-24 # working dir changed to output dir $ python my_app.py hydra.job.chdirTrue Working directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-17 Output directory : /home/jasha/dev/hydra/outputs/2023-04-18/13-43-17可以看到默认行为chdirFalseos.getcwd()返回启动目录/home/jasha/dev/hydra输出目录仍被创建但工作目录不切换显式开启chdirTrueos.getcwd()与hydra.runtime.output_dir指向同一个目录与 Hydra 1.1 行为一致。重要澄清输出目录照常创建需要特别强调chdir只控制是否切换工作目录并不控制是否创建输出目录。即使chdirFalseHydra 依然会为每次运行创建独立的输出目录并写入 Hydra 输出与日志文件# output dir and files are still created even if chdir is disabled: $ tree -a outputs/2023-04-18/13-43-24/ outputs/2023-04-18/13-43-24/ ├── .hydra │ ├── config.yaml │ ├── hydra.yaml │ └── overrides.yaml └── my_app.log其中.hydra目录可通过hydra.output_subdir改名置为null可禁用它内保存了config.yaml用户指定配置的完整 dumphydra.yamlHydra 自身配置的完整 dumpoverrides.yaml本次运行使用的命令行 overrides。my_app.log则是本次运行的应用日志。也就是说迁移到 1.2 后Hydra 的每运行一个独立输出目录 完整可追溯的元数据能力没有任何削弱变的只是进程工作目录的锚点。如何设置hydra.job.chdirhydra.job.chdir属于 Hydra 配置因此它既可以在配置文件中设置也可以在命令行以 override 形式覆盖方式一命令行覆盖适合临时验证python my_app.py hydra.job.chdirTrue方式二写入配置文件适合项目级统一设置hydra: job: chdir: True方式三在hydra.main()装饰器的 config_path 之外通过主配置文件集中管理。由于hydra.job是 Hydra 的内置配置组任何被 Hydra 加载的主配置primary config中都可以声明hydra.job.chdir。底层实现原理run_job中的目录切换逻辑理解底层实现有助于判断该配置在何种场景下生效。hydra.job.chdir的实际消费点位于 hydra/core/utils.py 的run_job()函数——这是每个作业真正执行前的核心入口old_cwd os.getcwd() ... output_dir str(OmegaConf.select(config, job_dir_key)) if job_subdir_key is not None: subdir str(OmegaConf.select(config, job_subdir_key)) output_dir os.path.join(output_dir, subdir) ... _chdir hydra_cfg.hydra.job.chdir if _chdir: os.chdir(output_dir) ret.working_dir output_dir else: ret.working_dir os.getcwd() ... if config.hydra.output_subdir is not None: hydra_output Path(config.hydra.runtime.output_dir) / Path(config.hydra.output_subdir) _save_config(task_cfg, config.yaml, hydra_output) _save_config(hydra_cfg, hydra.yaml, hydra_output) _save_config(config.hydra.overrides.task, overrides.yaml, hydra_output) ... try: ret.return_value task_function(task_cfg) ... finally: HydraConfig.instance().cfg orig_hydra_cfg if _chdir: os.chdir(old_cwd)从源码可以提炼出三条关键实现事实目录切换发生在任务函数执行之前run_job先计算output_dir单次运行取hydra.run.dir解析结果sweep 中再拼接job_subdir_key对应的子目录随后依据hydra.job.chdir决定是否os.chdir(output_dir)working_dir元数据随之变化chdirTrue时JobReturn.working_dir为输出目录否则为os.getcwd()即启动目录。该字段会写入作业返回结果供 launcher、sweeper 与 callback 使用finally中会恢复原目录无论任务成功、失败还是被KeyboardInterrupt中断run_job都会在清理阶段将工作目录恢复到old_cwd避免影响同一进程中后续作业的执行multirun 场景下尤为重要。另外注意在 hydra/_internal/instantiate/_instantiate2.py 中os.chdir/os.fchdir被列入默认安全的可实例化函数名单这保证了基于_instantiate2的instantiate机制可以正常处理含目录切换逻辑的代码路径。开启chdir后如何访问原始工作目录hydra.job.chdirTrue会让进程工作目录指向输出目录此时若仍需读取启动目录下的资源可以使用hydra.utils提供的两个辅助函数get_original_cwd()返回 Hydra 应用启动时的原始工作目录to_absolute_path(path)将相对路径解释为相对于原始工作目录并转为绝对路径若传入绝对路径则原样返回。其实现位于 hydra/utils.pydef get_original_cwd() - str: return the original working directory the Hydra application was launched from if not HydraConfig.initialized(): raise ValueError(get_original_cwd() must only be used after HydraConfig is initialized) ret HydraConfig.get().runtime.cwd ... def to_absolute_path(path: str) - str: if the input path is relative, its interpreted as relative to the original working directory p Path(path) if not HydraConfig.initialized(): base Path(os.getcwd()) else: base Path(get_original_cwd()) if p.is_absolute(): ret p else: ret base / p return str(ret)注意get_original_cwd()会从HydraConfig.get().runtime.cwd读取启动目录因此在未初始化 HydraConfig 时调用会抛出ValueError请在hydra.main装饰的函数内部使用。用法示例from hydra.utils import get_original_cwd, to_absolute_path import os hydra.main() def my_app(_cfg: DictConfig) - None: print(fCurrent working directory : {os.getcwd()}) print(fOrig working directory : {get_original_cwd()}) print(fto_absolute_path(foo) : {to_absolute_path(foo)}) print(fto_absolute_path(/foo) : {to_absolute_path(/foo)}) if __name__ __main__: my_app()输出示例chdirTrue时Current working directory : /Users/omry/dev/hydra/outputs/2019-10-23/10-53-03 Original working directory : /Users/omry/dev/hydra to_absolute_path(foo) : /Users/omry/dev/hydra/foo to_absolute_path(/foo) : /foo这组辅助函数在 Hydra 1.1 时代便已存在在 1.2 开启chdir后成为读取启动目录资源的标准姿势也是升级文档推荐的做法。相关测试行为在源码层面的验证仓库的 launcher 公共测试 hydra/test_utils/launcher_common_tests.py 对chdir相关行为进行了覆盖可作为理解语义的参考test_get_orig_dir通过overridesoverrides [hydra.job.chdirTrue]开启 chdir 后运行应用断言应用打印的os.getcwd()等于预期输出目录——验证了chdir 开启后工作目录切换为输出目录test_get_orig_dir_multirun在 multirun 场景下断言hydra.utils.get_original_cwd()返回启动时的 scratch 目录——验证了即使工作目录被切换原始目录仍可通过辅助函数取回test_to_absolute_path_multirun同时使用hydra.job.chdirTrue、hydra.sweep.dircli_dir、hydra.sweep.subdircli_dir_${hydra.job.num}等 overrides验证to_absolute_path在 sweep 子目录中对路径的正确解析相对路径基于原始工作目录拼接。这些测试同时覆盖了单次运行与 multirun 两种模式说明chdir的行为在两种模式下保持一致。升级路径与后续版本演进针对从 1.1 升级到 1.2 的用户官方在 Changes to jobs runtime working directory 中给出了非常简洁的迁移指引概括为如下清单检查你的应用是否依赖启动后工作目录 输出目录。若依赖请在应用配置或命令行中显式设置hydra.job.chdirTrue对依赖相对路径读取启动目录下资源的应用无需任何修改——1.2 默认行为不切换目录正是你想要的如果你同时想开启 chdir 又要读取启动目录资源请改用get_original_cwd()/to_absolute_path()而不是假设工作目录位置升级后建议在 multirun 场景做一次回归验证确认日志输出位置、hydra.runtime.output_dir、JobReturn.working_dir等元数据符合预期。值得注意的是该话题在后续版本中仍有持续演进与本变更直接相关的后续调整包括在 1.3 的破坏性变更清单 Breaking Changes in 1.3 中明确hydra.job.chdir的默认值仍为False且hydra.job.chdirnull不再被接受必须显式设置为True或False这进一步收紧了配置合法性杜绝了此前可能出现的隐式行为在 Prepare for 1.4 的升级准备文档中再次提醒如果应用依赖工作目录被切换到输出目录请显式设置hydra.job.chdirTrue不要依赖默认值。因此最稳妥的长期策略是永远显式声明hydra.job.chdir的值而不是依赖任何版本的默认行为。小结hydra.job.chdir是 Hydra 1.2 引入的一项小而关键的配置它把Hydra 是否自动切换进程工作目录到输出目录这一历史行为从隐式默认变为显式声明默认值为False。升级到 1.2 后默认情况下应用在启动目录运行输出目录照常创建.hydra元数据与日志不受影响需要旧行为时显式设置hydra.job.chdirTrue在 chdir 开启时通过get_original_cwd()/to_absolute_path()访问原始工作目录资源该配置的默认值在 1.3、1.4 中持续保持False并进一步收紧合法性校验建议在项目中始终显式声明。如需进一步了解输出目录的自定义模式hydra.run.dir、hydra.sweep.dir/hydra.sweep.subdir、hydra_override_dirnameresolver可参考 Customizing working directory patternhydra.job下其余字段name、id、num、env_set、env_copy等的完整说明见 Job Configuration。【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表