如何从 Nim 的导入失败中恢复?

Posted

技术标签:

【中文标题】如何从 Nim 的导入失败中恢复?【英文标题】:How do I recover from a failed import in Nim? 【发布时间】:2013-11-13 13:22:11 【问题描述】:

在Nim我可以写下面的代码来导入一个外部模块:

import myFancyPantsModule
...
# And here I'd use the fancyPants proc

只要我有模块就可以正常工作,但是对于可能下载代码但没有安装模块的人来说,编译将失败,并显示一条用户友好的消息:

$ nim c fancyProgram.nim
fancyProgram.nim(1, 7) Error: cannot open 'myFancyPantsModule'

有什么方法可以环绕import,以便我可以捕获它类似于异常并执行类似于when 语句的替代代码分支?我希望找到一些类似importable 的宏或我可以使用的东西:

when importable(myFancyPantsModule):
    # And here I'd use the fancyPants proc
else:
    quit("Oh, sorry, go to https://github.com/nim-lang/nimble and install " &
      " the myFancyPantsModule using the nimble package manager")

事实上,我想让一些模块成为可选模块,而不是简单的错误消息,这样编译仍然可以继续进行,也许功能会减少。这可能吗?

解决方案编辑:根据这里的答案是我的版本如何解决问题,首先您需要一个moduleChecker 二进制文件,其来源如下:

import os, osproc

let tmpFile = getTempDir() / "dynamicModuleChecker.nim"

proc checkModule(module: string) =
  except:
    echo "Cannot write ", tmpFile, " to check the availability of modules"
    quit(1)
  writeFile(tmpFile, "import " & module & "\n")

  finally: removeFile(tmpFile)

  except:
    echo("Cannot run \"nimrod check\" to check the availability of modules")
    quit(1)
  if execCmdEx("nim check " & tmpFile).exitCode != 0:
    echo("Cannot import module " & module & ".")
    quit(1)
  else:
    echo "OK"

if ParamCount() < 1:
  quit("Pass as first parameter the module to check")
else:
  checkModule(ParamStr(1))

然后,让这个命令可用,可以使用以下宏:

import macros

macro safeImport(module, message: string): stmt =
  if "OK" == gorge("./moduleChecker " & module.strVal):
    result = newNimNode(nnkStmtList).add(
      newNimNode(nnkImportStmt).add(
      newIdentNode(module.strVal)))
  else:
    error("\nModule " & module.strVal &
      " not available.\n" & message.strVal)

safeImport("genieos",
  "Please install \"http://gradha.github.io/genieos/\"")

不幸的是,必须生成一个单独的进程,不仅用于外部编译,还需要另一个生成临时文件来检查,因为当前版本中没有staticWrite在编译时生成文件时间。

【问题讨论】:

向 Nimrod 作者请求了更好的机制,请参阅 github.com/Araq/Nimrod/issues/671。 【参考方案1】:

据我所知,没有(简单的)方法可以做到这一点。您可以做的是在构建中使用单独的配置/检查阶段。例如:

import macros, os, osproc

proc checkModule(module, howtomessage: string) =
  except:
    echo("Cannot write .conftest.nim to check the availability of modules")
    quit(1)
  writeFile(".conftest.nim", "import " & module & "\n")

  except: nil
  removeFile(".conftest.nim")

  except:
    echo("Cannot run \"nimrod check\" to check the availability of modules")
    quit(1)
  if execCmdEx("nimrod check .conftest.nim").exitCode != 0:
    echo("Cannot import module " & module & ".")
    echo(howtomessage)
    quit(1)

checkModule "foobar", "Please install it using the Babel package manager"

然后运行类似:

nimrod cc --run configure.nim && nimrod cc main.nim

假设上面的代码存储在一个名为 configure.nim 的文件中,并且 nimrod 可执行文件在您的路径中(否则,您还必须在 configure.nim 中指定 nimrod 路径)。

【讨论】:

以上是关于如何从 Nim 的导入失败中恢复?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Maven 自动重试(从失败的模块恢复)?

如何从XPages / dojo中的“超时超时”中恢复

如何验证失败的 ElasticSearch 恢复?

从任务中恢复失败超过 max_retries

ALSA:无法从欠载中恢复,准备失败:管道损坏

ipod恢复及导入音乐