首页 > 编程语言 >Python中调用R语言代码(rpy)的一些报错和解决

Python中调用R语言代码(rpy)的一些报错和解决

时间:2024-10-17 13:20:54浏览次数:7  
标签:plot Python rpy 报错 file pdf path data png

我搭建网站的过程中,需要将可视化的图下载下来,使用Echarts是比较好看,但是下载的是图片格式(png),项目需求是下载PDF的R绘制的图。

所以我这边使用Python调用R代码,借rpy实现这个功能。

在 Python 中调用 R 代码有多种方式,其中最常用的是通过 rpy2 库,它允许在 Python 中运行 R 代码并获取结果。

rpy2 是一个非常强大的 Python 库,可以直接在 Python 中运行 R 代码并返回结果。

安装 rpy2:

pip install rpy2 
然后就开始报错了,一个一个来:

1.

R_HOME must be set in the environment or Registry
Process finished with exit code 2

已解决,解决方案:配置环境变量:

path里还需要配置R_HOME下的bin别忘了。

 2.

R调用成功,但是生成的文件保存在本地,浏览器访问不到。

浏览器有同源政策,需要跨域。但是访问本地文件这种操作一般是不允许的,我换了存储了路径,保存在代码同一目录下,就可以了。

 在 Django 视图中,使用 rpy2 调用 R 生成图像,并保存到 MEDIA_ROOT,然后返回图像的 URL:

①确保在 settings.py 中配置 MEDIA_ROOTMEDIA_URL,用于保存和访问生成的图像。

settings.py:

# settings.py
import os

# 用于保存媒体文件的目录
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

②视图调用生成PNG和PDF并返回URL:

views.py:

def generate_r_plot():
    import rpy2.robjects as robjects  # 这个为什么要放在这里才有效啊,我真麻了

    # 获取保存图像的目录
    image_dir = os.path.join(settings.MEDIA_ROOT, 'rplots', 'analysisDiff')
    if not os.path.exists(image_dir):
        os.makedirs(image_dir)
    # 定义保存 PNG 和 PDF 的文件路径,使用当前时间戳命名文件
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
    png_filename = f"analysis_plot_{timestamp}.png"
    pdf_filename = f"analysis_plot_{timestamp}.pdf"
    png_path = os.path.join(image_dir, png_filename)
    pdf_path = os.path.join(image_dir, pdf_filename)

    # 数据文件路径 (假设 test.txt 位于项目的 data 目录下)
    data_file = os.path.join(settings.DATA_ROOT, 'analysisDiff', 'test.txt')

    # import chardet
    # with open(data_file, 'rb') as f:
    #     result = chardet.detect(f.read())
    #     print(result) # 这个文件读出来就是ascii码了

    # 转换路径为R兼容的格式 总觉得这样很多重复代码
    pdf_path_r = pdf_path.replace("\\", "/")
    png_path_r = png_path.replace("\\", "/")
    data_path_r = data_file.replace("\\", "/")

    # 将路径传递给R环境

    robjects.globalenv['pdf_path_r'] = pdf_path_r
    robjects.globalenv['png_path_r'] = png_path_r
    robjects.globalenv['data_path_r'] = data_path_r

    # 调用 R(PNG 和 PDF 两种格式)
    r = robjects.r
    r('''
       library(data.table)  
       library(dplyr)       
       library(ggplot2)
       library(tidyr)
       df <- read.table(data_path_r, header = T, check.names = F, fileEncoding = "ASCII")
       df1 <- df %>% pivot_longer(cols = normal:disease, names_to = "category", values_to = "ExpressionFPKM")
       p <- ggplot(df1, aes(x = dataset, y = ExpressionFPKM, fill = category)) +geom_col(width=0.5,position='dodge')
       ggsave(pdf_path_r,width = 20,height = 6,family="GB1")
       ggsave(png_path_r,width = 20,height = 6)
       ''')
    return png_path, pdf_path


# 差异分析异步出图-用R绘图展示PNG以及下载PDF
def diff_analysis_plot_use_r(request):
    png_path, pdf_path = generate_r_plot()

    if not os.path.exists(pdf_path) or not os.path.exists(png_path):
        return JsonResponse({'error': 'Plot generation failed'}, status=500)

    # 返回 PNG 图像的 URL 和 PDF 路径
    # pdf_url = f'/media/rplots/analysisDiff/{os.path.basename(pdf_path)}'
    pdf_name = os.path.basename(pdf_path)  # pdf不需要路径了,只要名字就可以
    png_url = f'/media/rplots/analysisDiff/{os.path.basename(png_path)}'

    return JsonResponse({'png_url': png_url, 'pdf_name': pdf_name})

③为视图添加url路由:

urlpatterns = [
   path('/analysis/differential/plot/R', diff_analysis_plot_use_r),
]

④前端ajax发送请求并展示图像:

js部分:

               document.getElementById('plot-ECharts').style.display = 'none';
                document.getElementById('plot-R').style.display = 'block';
                document.getElementById('downloadLink').style.display = 'inline'; // 下载按钮给加上
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    data: {},
                    url: '/cuDB/analysis/differential/plot/R',
                    success: function (data) {
                        pdfname = data.pdf_name;
                        $('#R_png').attr('src', data.png_url).show();

                        // 动态更新a标签的href
                        const downloadLink = document.getElementById('downloadLink');
                        downloadLink.href = '/cuDB/analysis/differential/plot/R/download/?file_path=' + pdfname;
                        console.log("这里2")
                    },
                });

 按钮部分:

                <!--为echart准备一个具备大小的dom 大小还要调整 -->
                <div id="plot-ECharts" style="width: 100%;height: 300px;margin-left: auto">
                </div>

                <!-- 用于显示 R 生成的图像 -->
                <div id="plot-R">
                    <img id="R_png" src="" alt="Scatter Plot" style="display:none; max-width: 100%;">
                </div>

 ⑤项目结构大致如下:

your_project/

├── your_app/
│   ├── migrations/
│   ├── templates/
│   │   └── template.html
│   ├── views.py
│   ├── urls.py
│   └── ...

├── media/  # 保存 R 生成图像的文件夹(实际我分得更细,还有一层)
│   └── rplots/

├── settings.py
└── ...

3.

NotImplementedError:    

Conversion rules for `rpy2.robjects` appear to be missing. Those    rules are in a Python `contextvars.ContextVar`. This could be caused    by multithreading code not passing context to the thread.    Check rpy2's documentation about conversions.

NotImplementedError 的间歇性出现通常与以下因素有关:

  1. 多线程/异步环境:如果在多线程或异步代码中调用 generate_r_plot,可能导致上下文丢失,导致不一致的行为。

  2. 上下文管理:在某些情况下,未正确管理上下文会导致错误。例如,某些线程可能没有访问到正确的上下文变量。

  3. R 和 rpy2 版本兼容性:不同版本之间的兼容性问题可能导致间歇性的错误。某些函数在不同版本下的实现可能不同。

  4. 变量的生命周期:确保在使用之前,所有传递给 globalenv 的变量都是有效的。如果变量在某个线程中被修改或失效,可能会导致错误。

  5. 运行环境:在不同的环境(如 Jupyter Notebook 和标准 Python 脚本)中,行为可能会有所不同。

我发现两个浏览器一起访问,就会报错,做了一个很低智的东西。那么显然我们的代码的问题是上面的1,多线程问题。

还没解决,sorry。

 4.调用R生成的PDF,对这个PDF文件实现下载功能:

直接定义一个a标签,动态更新a标签的href:

html:

  <!-- 下载按钮 -->
                            <a id="downloadLink" href="#" class="btn btn-primary">download pdf</a>

 js部分:在上面调用的时候就完成了这个动态更新的动作

                document.getElementById('plot-ECharts').style.display = 'none';
                document.getElementById('plot-R').style.display = 'block';
                document.getElementById('downloadLink').style.display = 'inline'; // 下载按钮给加上
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    data: {},
                    url: '/cuDB/analysis/differential/plot/R',
                    success: function (data) {
                        pdfname = data.pdf_name;
                        $('#R_png').attr('src', data.png_url).show();

                        // 动态更新a标签的href
                        const downloadLink = document.getElementById('downloadLink');
                        downloadLink.href = '/cuDB/analysis/differential/plot/R/download/?file_path=' + pdfname;
                    },
                });

 后端加个路径:

path('/analysis/differential/plot/R/download/', diff_analysis_download),

 views.py:

def diff_analysis_download(request):
    file_path = request.GET.get('file_path')  # 从查询参数获取文件路径
    print(file_path)
    if file_path:
        # 构建完整的文件系统路径
        abs_file_path = os.path.join(settings.MEDIA_ROOT, 'rplots', 'analysisDiff', file_path)

        # 检查文件是否存在
        if os.path.exists(abs_file_path):
            with open(abs_file_path, 'rb') as file:
                response = HttpResponse(file.read(), content_type='application/pdf')
                response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"'
                return response
        else:
            return HttpResponse('文件不存在', status=404)
    else:
        return HttpResponse('文件路径无效', status=400)

 

标签:plot,Python,rpy,报错,file,pdf,path,data,png
From: https://www.cnblogs.com/isayruby/p/18441627

相关文章

  • python+flask框架的大学生创新实验室设备资产管理系统小程序端8(开题+程序+论文) 计算
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景在当前高等教育环境中,大学生创新实验室作为培养学生实践能力和创新思维的重要平台,其设备资产管理的高效性和准确性显得尤为重要。然而,现有......
  • python+flask框架的传智健康医疗项目设计与实现(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景随着信息技术的飞速发展,健康医疗行业正经历着前所未有的变革。关于健康医疗信息化的研究,现有研究主要以电子病历系统、远程医疗服务以及医......
  • python+flask框架的传智健康医疗项目设计与实现(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景随着信息技术的飞速发展和人口老龄化的加剧,健康医疗行业正经历着前所未有的变革。当前,国内外关于健康医疗信息化的研究主要集中在医疗信息......
  • python+flask框架的城固一中学生信息管理系统的设计与实现(开题+程序+论文) 计算机毕
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景在当前信息化时代背景下,学校信息管理系统的建设已成为提升教育管理水平、优化资源配置、提高教学效率的重要手段。关于学生信息管理系统的......
  • 【计算机毕设选题推荐】基于Python的智能停车管理系统的设计与实现 【附源码+数据库+
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • 【计算机毕设选题推荐】基于Python的学生选课系统的设计与实现 【附源码+数据库+部署
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • python基础(数据类型一)
    在python语言中数据类型包含整数(int),浮点(float),复数(complex),布尔(bool),字符串(str),列表(list),元组(tuple),字典(dict),集合(set)以及空值(None)#数据类型比较多,今天之讲解整数(int),浮点(float),复数(complex),布尔(bool)这三个,其余的类型会单独分六个章节逐一讲解。一.整数(int):1.整数表示数值,没有小......
  • supervisor使用报错解决
    常用命令supervisorctlstatus查看状态supervisorctlreload重新载入配置文件supervisorctlstartall/ftp启动所有/指定的程序进程supervisorctlstopall/frp关闭所有/指定的程序进程一.简化后的supervisord.conf配置文件内容:[unix_http_s......
  • 通过Python爬虫获取商品销量数据,轻松掌握市场动态
    为什么选择Python爬虫?简洁易用:Python语言具有简洁的语法和丰富的库,使得编写爬虫变得简单高效。强大的库支持:Python拥有强大的爬虫框架(如Scrapy、BeautifulSoup、Requests等),可以快速实现数据抓取和解析。社区活跃:Python的开发者社区非常活跃,您可以轻松找到解决方案和示例代码。......
  • LeetCode第六题:锯齿形转换(Python)
    一.题目要求及实例将给定的字符串,转化为锯齿形。锯齿形的行数给定。按序输出转换后的字符串。二.初始思路(1)二维数组的大小竖着写入二维数组较困难,所以想到了先横着写,再取转置。首先需要知道二维数组的大小。参数中给的numRows即为行数,所以要考虑的就是二维数组的列数。......