zoukankan      html  css  js  c++  java
  • 手动搭建latex公式渲染服务器

    latex公式渲染有两种类型,一种是HTML形式展示公式,另一种是图片形式展示公式。如果是HTML形式展示公式,渲染是在前端完成的,一般会比较缓慢。知乎采取的方式是以图片形式展示公式。codecogs是一个latex公式渲染服务,它根据get请求返回一个svg图片。例如:

    本文介绍ubuntu下搭建类似codecogs的公式渲染服务。

    一、安装latex

    sudo apt-get install latex
    sudo apt-get install latex-cjk-chinese
    

    二、latex命令介绍

    latex命令用于把tex文件转换成pdf文件或者dvi文件。dvi是一种设备无关的可打印文件格式。
    输入dvi按两次tab可以找到dvisvgm,此命令将dvi文件转为svg。

    三、编写服务程序

    使用flask编写服务,通过命令行的方式调用latex获取svg。在返回时需要注意两点:

    • 设置好content-type,否则客户端不知道你返回的是什么格式的图片
    • 跨域访问并不需要设置,因为加载的是静态资源。跨域访问只需要在header中设置: "Access-Control-Allow-Origin": "*"

    使用latex命令时需要注意:

    • documentclass必须是minimal,这样能够保证生成的文件尽量小。
    • dvisvgm --no-fonts --no-styles,把dvi转为svg时取消导出字体和格式,而只是简单导出一张图片,否则客户端找不到这些字体和格式。
    • 使用latex --interaction=nonstopmode,能够保证即便报错也不会阻塞
    • 要引入amsmath,否则许多宏会找不到
    • 为了防止用户上传不合法公式造成超时的现象,需要使用subprocess模块,它是非阻塞的,父进程可以对子进程的运行时间进行监听。

    TODO:

    • 添加缓存功能:对某个公式的请求可能很多,每次不需要调用latex重新生产,直接使用缓存结果。这个优化可能没有必要,因为当查询分布特别分散时,这个优化费力不讨好。
    • 添加统计功能:统计不同网站的请求次数,用来查看都有哪些人使用了本服务。其实调用别人服务是一件很危险的事情。调用别人的服务就是信任别人的服务,把别人的服务当做自己的一部分。当别人变得不可信任时,自己也就危险了。比如latex公式服务把返回的svg图片统一替换成某个不合法的图片。
    import os
    import signal
    import subprocess
    
    from flask import Flask, request, Response
    
    app = Flask(__name__)
    
    file_id = 0
    latex_dir = os.path.join(os.path.expanduser("~"), "latex-server")
    if not os.path.exists(latex_dir):
        os.mkdir(latex_dir)
    
    
    def run_command(s, log_file):
        pro = subprocess.Popen(s, shell=True, preexec_fn=os.setsid)
        try:
            pro.wait(1)  # 最多等待1秒钟
        except Exception as ex:
            print(ex)
            # pro.terminate()
            os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # 杀死一个进程组
            raise ex
    
    
    def gets(formula):
        global file_id
        file_id += 1
        now = file_id
        tex_file, dvi_file, svg_file, log_file = [os.path.join(latex_dir, "{}.{}".format(
            now, file_type)) for file_type in "tex dvi svg log".split()]
        open(tex_file, mode='w').write(r"""
    documentclass{minimal}
    usepackage{amsmath}
    egin{document}
    $$%s$$
    end{document}
        """ % formula)
        try:
            run_command("latex  --interaction=nonstopmode --output-directory  {} {}".format(
                latex_dir, tex_file), log_file)
            run_command(
                "dvisvgm --no-fonts --no-styles -c2,2 -o {} {}".format(svg_file, dvi_file), log_file)
            svg = open(svg_file).read()  # 如果不存在,那就直接抛出异常吧
            return svg
        except Exception as ex:
            raise ex
        finally:
            # 清理文件
            for i in "tex dvi log aux svg".split():
                filename = os.path.join(latex_dir, "{}.{}".format(now, i))
                if os.path.exists(filename):
                    os.remove(filename)
    
    
    @app.route("/render")
    def render():
        formula = request.args['formula']
        try:
            resp = gets(formula)
            return Response(response=resp, headers={
                "Content-Type": "image/svg+xml"
            })
        except Exception as ex:
            print(ex)
            return Response(status=500)
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=9988, debug=True)
    
    

    参考资料

    https://cloud.tencent.com/developer/article/1015883

  • 相关阅读:
    Spring学习总结(3)——Spring配置文件详解
    Hadoop学习总结(1)——大数据以及Hadoop相关概念介绍
    华为云文字识别关键技术和特别需要注意的事宜
    如何不用BPM配置时间
    华为云DevCloud为开发者提供高效智能的可信开发环境
    【HC资料合集】2019华为全联接大会主题资料一站式汇总,免费下载!
    在modelarts上部署mask-rcnn模型
    独立物理机和虚拟机比较有什么优势?
    解惑Python模块学习,该如何着手操作...
    sar命令,linux中最为全面的性能分析工具之一
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/10126152.html
Copyright © 2011-2022 走看看