在Ruby on Rails中使用PyCall调用本地Python模块失败问题排查
问题解决:Rails中调用Python脚本的路径问题与替代方案
一、当前报错原因(非语法错误)
你的代码语法没有问题,报错核心是路径配置错误:
你使用的绝对路径/lib/assets/python指向的是系统根目录下的lib文件夹,而非你的Rails项目根目录内的对应路径。PyCall无法定位到目标Python文件,因此抛出ModuleNotFoundError。
二、修正PyCall的代码
利用Rails提供的Rails.root获取项目根目录,拼接出正确的Python文件所在路径:
require 'pycall' # 拼接项目内的完整路径 python_dir = Rails.root.join('lib', 'assets', 'python').to_s PyCall.sys.path.append(python_dir) file_import = PyCall.import_module("the_file")
三、Rails中运行Python脚本的其他方案
1. 直接执行系统命令
如果不需要在Ruby和Python间传递复杂数据,可直接用Ruby的系统命令执行脚本:
# 基础写法 system("python3 #{Rails.root.join('lib', 'assets', 'python', 'the_file.py')}") # 安全写法(避免shell注入,同时捕获输出和错误) require 'open3' stdout, stderr, status = Open3.capture3("python3", Rails.root.join('lib', 'assets', 'python', 'the_file.py').to_s) # stdout为脚本输出内容,stderr为错误信息,status.exitstatus为脚本退出码
2. 封装为Rake任务
若需定时或批量执行Python脚本,可封装成Rake任务便于调用:
# lib/tasks/python_task.rake namespace :python do desc "执行目标Python脚本" task run_script: :environment do python_path = Rails.root.join('lib', 'assets', 'python', 'the_file.py').to_s system("python3 #{python_path}") puts "Python脚本执行完成" end end
终端调用方式:bundle exec rake python:run_script
3. 后台异步执行
如果Python脚本执行耗时较长,建议用Sidekiq等框架异步处理,避免阻塞Web请求:
# app/workers/python_script_worker.rb class PythonScriptWorker include Sidekiq::Worker def perform python_path = Rails.root.join('lib', 'assets', 'python', 'the_file.py').to_s system("python3 #{python_path}") end end
调用方式:PythonScriptWorker.perform_async
内容的提问来源于stack exchange,提问作者Benjamin Kim
相关产品推荐
相关产品推荐

