动态导入在运行时从编译输出中指定的模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态导入在运行时从编译输出中指定的模块相关的知识,希望对你有一定的参考价值。

Overview

我有一个项目,我在其中创建了一个简单的clojure编译器,它将clojure代码转换为python代码(这将被上传到clojars)。另外,我有一个python项目,将打包并使pip可安装。虽然他们已经准备好了,但我还没有完全打包。

The problem

用户在clojure中指定模型,然后将该模型编译为python,其中输出为<user_model_name>.py,此输出具有类结构。然后,我已经获取python输出的python包并从该python输出中提取方法并对该模型执行推断。但是,这是我第一次做这样的项目,所以我迫切需要如何实际找到编译文件的指针,给定一些文件路径(可能)(最好只是模型名称),然后加载该模型在运行时python代码中。

在本地,用importlib module很容易做到这一点,因为我知道如何将我的代码导向输出。但是,一旦系统上安装了两个软件包,我真的不确定这样做的最佳方法是什么。

The aim

最终目标是拥有这样的东西:

用户编写模型: (def if-model (foppl-query (let [x1 (sample (normal 0 1)) x2 (sample (normal 0 1))] (if (> x1 0) (observe (normal x2 1) 1) (observe (normal -1 1) 1)) x1)))

然后在终端呼叫:

lein exec compiler.clj -p if-model.clj

然后用户将编写一个调用python包的脚本:

import ... from <python_package> import inference as infer <user defined parameters> ... run_alg = infer.<inference_obj>(<filename or Path to module>, other_params)

(文件路径可能要求最终用户太多)

导入需要在运行时在<inference_obj>()内发生,这是需要模型类的推理算法的实例化。

我已经googled高低,我认为我将不得不使用importlib库来创建一个finder和loader,但我不完全确定如何解决这个问题。第二种方法,虽然我不确定这是否可行,但是在python中使用subprocess模块并在python模块中编写一个bash脚本,在我的python包中调用<user_model_name>.clj上的clojure编译器,然后设置一些全局PATH变量到编译输出的位置,所以<python_package>知道在哪里看。所以在终端,python python_bash_script.py <user_model_name>.clj这样的事情。但同样,我真的不确定,所以任何指针都会非常感激。

感谢您抽出宝贵时间阅读我的问题。

答案

虽然我没有直接回答你的问题,但让我评论一些细节。

使用importlib将是我认为最简单的选择。一旦你在文件的顶部导入了这样一个生成的模块,很明显你是否已成功加载它。

生成Python代码时,结果可能只是我想的一个函数,因为你的Clojure代码也有一个函数。

如果Python是项目的主要部分,请查看Hy language。它是用纯Python实现的Clojure语言的克隆。大多数clojure.core函数,不可变数据结构和其他东西都存在。

也许你可以在你的项目中跳过Clojure在Hy中编写一些Clojure代码。

此外,在您的示例中,您在lein实用程序和exec插件中运行Clojure编译器。如果你想分发那个Clojure编译器,它应该只是uberjar。

以上是关于动态导入在运行时从编译输出中指定的模块的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft vcredist在运行时使用的版本比清单中指定的版本高

编译时出错 - 在初始化程序中指定的未知字段

获取魔术线/shebang中指定的编码(来自模块内)

输出超出range()函数中指定的最大值

Java 反射之调用运行时类中指定的属性

从使用 jQuery 的代码中指定的元素中选择具有给定类的下一个元素