通过 Erlport 执行的函数停止响应
Function executed via Erlport stops responding
我正在写我的论文申请。我需要线性规划,但我的应用程序是用 Elixir 编写的,这确实不是此类操作的语言。这就是为什么我决定使用 Erlport 作为 Elixir 依赖项,它能够将 Python 代码与 Elixir 连接起来。我还使用 Pulp 作为 python 库进行优化。
长生不老药版本:1.10.4,
错误端口版本:0.10.1,
Python版本:3.8.5,
纸浆版本:2.3
我已经为 Elixir-Python 通信编写了这样一个模块,它利用 GenServer 作为 Elixir 和 Python 之间的主要 'communication hub':
defmodule MyApp.PythonHub do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_opts) do
path = [:code.priv_dir(:feed), "python"]
|> Path.join() |> to_charlist()
{:ok, pid} = :python.start([{ :python_path, path }, { :python, 'python3' }])
{:ok, pid}
end
def handle_call({:call_function, module, function_name, arguments}, _sender, pid) do
result = :python.call(pid, module, function_name, arguments)
{:reply, result, pid}
end
def call_python_function(file_name, function_name, arguments) do
GenServer.call(__MODULE__, {:call_function, file_name, function_name, arguments}, 10_000)
end
end
GenServer模块正在调用python文件,其中包含这样一个函数:
def calculate_meal_4(products_json, diet_json, lower_boundary, upper_boundary, enhance):
from pulp import LpMinimize, LpProblem, LpStatus, lpSum, LpVariable, value
import json
products_dictionary = json.loads(products_json)
print(products_dictionary)
diets_dictionary = json.loads(diet_json)
print(diets_dictionary)
model = LpProblem(name="diet-minimization", sense=LpMinimize)
# ... products setup ...
x = LpVariable("prod_1_100g", lower_boundary, upper_boundary)
y = LpVariable("prod_2_100g", lower_boundary, upper_boundary)
z = LpVariable("prod_3_100g", lower_boundary, upper_boundary)
w = LpVariable("prod_4_100g", lower_boundary, upper_boundary)
optimization_function = # ... optimization function setup ...
model += # ... optimization boundary function setup ...
model += optimization_function
print(model)
solved_model = model.solve()
print(value(model.objective))
return [value(x), value(y), value(z), value(w)]
对 GenServer 本身的调用如下所示:
PythonHub.call_python_function(:diets, python_function, [products_json, meal_statistics_json, @min_portion, @max_portion, @macro_enhancement])
其中 python_function 是 :calculate_meal_4 和 products_json 和 meal_statistic_json 是包含所需数据的 json。
通过 python3 diets.py 调用 calculate_meal_4 时,会启动 python 脚本上面有一些例子,但是真实的(取自应用程序),数据一切正常 - 我几乎没有时间就得到了最小化的结果。通过 Elixir Erlport 调用 python 脚本时出现问题。查看打印输出,我可以看出它似乎一直有效,直到
solved_model = model.solve()
被调用。然后脚本似乎冻结了,GenServer 终于在 GenServer.call 函数上达到超时。
我还在一个简单的 python 测试文件上测试了调用:
def pass_var(a):
print(a)
return [a, a, a]
而且效果很好。
这就是为什么我现在真的很困惑,我正在寻找任何建议。可耻的是我什么都没找到。
嗯,调用外部求解器可能会冻结进程。
鉴于 you can execute bash scripts using elixir, you can easily change the python script to be command line executable (I recommend click)。然后,您可以将输出写入 .json
或 .csv
文件,并在完成后用 Elixir 将其读回。
@click.group()
def cli():
pass
@cli.command()
@click.argument('products_json', help='your array of products')
@click.argument('diet_json', help='your dietary wishes')
@click.option('--lower-bound', default=0, help='your minimum number of desired calories')
@click.option('--upper-bound', default=100, help='your maximum number of desired calories')
@click.option('--enhance', default=False, help="whether you'd like to experience our enhanced experience")
def calculate_meal_4(products_json, diet_json, lower_boundary, upper_boundary, enhance):
pass
if __name__ == '__main__':
cli()
然后您可以使用 python3 my_file.py <products_json> <diet_json> ...
等调用它。
你甚至可以validate the JSON and then return the parsed data directly.
我正在写我的论文申请。我需要线性规划,但我的应用程序是用 Elixir 编写的,这确实不是此类操作的语言。这就是为什么我决定使用 Erlport 作为 Elixir 依赖项,它能够将 Python 代码与 Elixir 连接起来。我还使用 Pulp 作为 python 库进行优化。
长生不老药版本:1.10.4, 错误端口版本:0.10.1, Python版本:3.8.5, 纸浆版本:2.3
我已经为 Elixir-Python 通信编写了这样一个模块,它利用 GenServer 作为 Elixir 和 Python 之间的主要 'communication hub':
defmodule MyApp.PythonHub do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_opts) do
path = [:code.priv_dir(:feed), "python"]
|> Path.join() |> to_charlist()
{:ok, pid} = :python.start([{ :python_path, path }, { :python, 'python3' }])
{:ok, pid}
end
def handle_call({:call_function, module, function_name, arguments}, _sender, pid) do
result = :python.call(pid, module, function_name, arguments)
{:reply, result, pid}
end
def call_python_function(file_name, function_name, arguments) do
GenServer.call(__MODULE__, {:call_function, file_name, function_name, arguments}, 10_000)
end
end
GenServer模块正在调用python文件,其中包含这样一个函数:
def calculate_meal_4(products_json, diet_json, lower_boundary, upper_boundary, enhance):
from pulp import LpMinimize, LpProblem, LpStatus, lpSum, LpVariable, value
import json
products_dictionary = json.loads(products_json)
print(products_dictionary)
diets_dictionary = json.loads(diet_json)
print(diets_dictionary)
model = LpProblem(name="diet-minimization", sense=LpMinimize)
# ... products setup ...
x = LpVariable("prod_1_100g", lower_boundary, upper_boundary)
y = LpVariable("prod_2_100g", lower_boundary, upper_boundary)
z = LpVariable("prod_3_100g", lower_boundary, upper_boundary)
w = LpVariable("prod_4_100g", lower_boundary, upper_boundary)
optimization_function = # ... optimization function setup ...
model += # ... optimization boundary function setup ...
model += optimization_function
print(model)
solved_model = model.solve()
print(value(model.objective))
return [value(x), value(y), value(z), value(w)]
对 GenServer 本身的调用如下所示:
PythonHub.call_python_function(:diets, python_function, [products_json, meal_statistics_json, @min_portion, @max_portion, @macro_enhancement])
其中 python_function 是 :calculate_meal_4 和 products_json 和 meal_statistic_json 是包含所需数据的 json。
通过 python3 diets.py 调用 calculate_meal_4 时,会启动 python 脚本上面有一些例子,但是真实的(取自应用程序),数据一切正常 - 我几乎没有时间就得到了最小化的结果。通过 Elixir Erlport 调用 python 脚本时出现问题。查看打印输出,我可以看出它似乎一直有效,直到
solved_model = model.solve()
被调用。然后脚本似乎冻结了,GenServer 终于在 GenServer.call 函数上达到超时。
我还在一个简单的 python 测试文件上测试了调用:
def pass_var(a):
print(a)
return [a, a, a]
而且效果很好。
这就是为什么我现在真的很困惑,我正在寻找任何建议。可耻的是我什么都没找到。
嗯,调用外部求解器可能会冻结进程。
鉴于 you can execute bash scripts using elixir, you can easily change the python script to be command line executable (I recommend click)。然后,您可以将输出写入 .json
或 .csv
文件,并在完成后用 Elixir 将其读回。
@click.group()
def cli():
pass
@cli.command()
@click.argument('products_json', help='your array of products')
@click.argument('diet_json', help='your dietary wishes')
@click.option('--lower-bound', default=0, help='your minimum number of desired calories')
@click.option('--upper-bound', default=100, help='your maximum number of desired calories')
@click.option('--enhance', default=False, help="whether you'd like to experience our enhanced experience")
def calculate_meal_4(products_json, diet_json, lower_boundary, upper_boundary, enhance):
pass
if __name__ == '__main__':
cli()
然后您可以使用 python3 my_file.py <products_json> <diet_json> ...
等调用它。
你甚至可以validate the JSON and then return the parsed data directly.