修复由于打开任务或IO而挂起的预编译
在Julia1.10或更高版本上,您可能会看到以下消息:
这可能会重复。 如果它继续重复而没有提示它会自行解决,那么您可能会有一个需要修复的"预编译挂起"。 即使它是暂时的,您可能更愿意解决它,以便用户不会受到此警告的困扰。 本页将引导您了解如何分析和解决此类问题。
如果你听从建议,打 Ctrl-C,你可能会看到
^C Interrupted: Exiting precompilation... 1 dependency had warnings during precompilation: ┌ Test1 [ac89d554-e2ba-40bc-bc5c-de68b658c982] │ [pid 2745] waiting for IO to finish: │ Handle type uv_handle_t->data │ timer 0x55580decd1e0->0x7f94c3a4c340
这条信息传达了两个关键信息:
*挂起是在预编译期间发生的 测试1,一个依赖 测试2 (我们试图装载的包裹 使用Test2)
*在预编译期间 测试1,朱莉娅创造了一个 定时器 对象(使用 ?定时器 如果你不熟悉计时器),它仍然是开放的;直到关闭,进程被挂起
如果这是一个足够的提示,让你弄清楚如何 定时器=定时器(args。..) 正在创建,一个很好的解决方案是添加 等待(计时器) 如果 定时器 最终自行完成,或 关闭(计时器) 如果你需要强制关闭它,在决赛之前 结束 的模块。
但是,有些情况可能不是那么简单。 通常最好的选择是首先确定挂起是由于Test1中的代码还是由于Test1的依赖项之一:
*备选案文1: Pkg。添加("水") 和使用https://juliatesting.github.io/Aqua.jl/dev/#Aqua.test_persistent_tasks-Tuple{Base.PkgId}[水族。test_persistent_tasks]. 这应该可以帮助您确定导致问题的软件包,之后说明 下应遵循。 如果需要,您可以创建一个 PkgId,PkgId 作为 基地。PkgId(UUID("。.."),"Test1"),在哪里 ... 来自 uuid 进入 Test1/项目。汤姆尔.
*选项2:手动诊断挂起的来源。
手动诊断:
-
Pkg。开发("Test1") -
注释掉所有的代码
包括d或定义于测试1,_except_的使用/导入发言。 -
试试
使用Test2(甚至使用Test1假设也挂起)再次
现在我们到达了一个岔路口:要么
*挂起仍然存在,表明它是 由于您的一个依赖项 *挂起消失,表明它是 由于您的代码中的某些内容。
诊断和修复因包依赖而挂起的问题
使用二进制搜索来识别有问题的依赖关系:从注释掉一半的依赖关系开始,然后当你隔离哪一半负责时,注释掉那一半的一半,等等。 (您不必将它们从项目中删除,只需注释掉 使用/进口 发言。)
一旦你确定了一个嫌疑犯(在这里我们称之为 你的想法,你的想法),首先尝试预编译该包。 如果它在预编译期间也挂起,请继续向后追逐问题。
然而,最有可能的 你的想法,你的想法 将预编译罚款。 这表明它在函数中 你的想法是关于问题的。__init__,在预编译期间不运行 你的想法,你的想法 但是_does_在任何加载的包中 你的想法,你的想法. 为了测试这个理论,建立一个最小工作示例(MWE),类似于
(@v1.10) pkg> generate MWE
Generating project MWE:
MWE\Project.toml
MWE\src\MWE.jl
其中的源代码 MWE。jl 是
module MWE
using ThePackageYouThinkIsCausingTheProblem
end
你还补充道 你的想法,你的想法 到MWE的依赖关系。
如果那个MWE重现了绞刑,你就找到了罪魁祸首: 你的想法是关于问题的。__init__ 必须创建 定时器 对象。 如果timer对象可以安全 接近/接近d,这是一个很好的选择。 否则,最常见的解决方案是避免在_any_包正在预编译时创建计时器:添加
ccall(:jl_generating_output, Cint, ()) == 1 && return nothing
作为第一行 你的想法是关于问题的。__init__,并且它将避免在任何Julia进程中进行任何初始化,其目的是预编译包。
修复包代码以避免挂起
在你的包中搜索暗示性的单词(这里像"计时器"),看看你是否能确定问题的产生位置。 请注意,类似于_definition_的方法
maketimer() = Timer(timer -> println("hi"), 0; interval=1)
本身没有问题:只有在以下情况下才会导致这个问题 使蒂默 在定义模块时被调用。 这可能发生在顶级语句中,例如
const GLOBAL_TIMER = maketimer()
或者它可能发生在一个https://github.com/JuliaLang/PrecompileTools.jl[预编译工作负载]。
如果你很难确定原因行,那么考虑做一个二进制搜索:注释掉你的包的部分(或者 包括 行以省略整个文件),直到您减少了范围内的问题。