在Python中禁止Plotly以任何形式与网络通信

2024-05-21 02:01:23 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有可能让Plotly(从Python内部使用)变成“严格的本地”呢?换句话说,有没有可能以某种方式使用它,以保证它不会以任何理由与网络联系?在

这包括程序试图联系Plotly服务(因为这是商业模式),也包括确保在生成的html中单击任何地方都不会链接到Plotly或其他任何地方。在

当然,我希望能够在连接到网络的生产机器上执行此操作,因此拔出网络连接不是一个选项。在


Tags: 程序网络机器链接html选项地方方式
3条回答

我没有做过任何广泛的测试,但看起来Plot.ly公司提供“脱机”模式:

https://plot.ly/python/offline/

一个简单的例子:

from plotly.offline import plot
from plotly.graph_objs import Scatter

plot([Scatter(x=[1, 2, 3], y=[3, 1, 6])])

你可以安装Plot.ly公司通过pip,然后运行上面的脚本生成一个静态HTML文件:

^{pr2}$

当我从终端运行此程序时,我的web浏览器将打开到以下文件URL:

file:///some/path/to/temp-plot.html

这将呈现一个对文件系统完全本地的交互图。在

我想我已经想出了一个解决办法。首先,你需要下载开源软件普洛特利.jsfile。然后我有一个函数,写在下面,它将从python绘图生成javascript,并引用plotly的本地副本-最新.min.js. 见下文:

import sys
import os
from plotly import session, tools, utils
import uuid
import json

def get_plotlyjs():
    path = os.path.join('offline', 'plotly.min.js')
    plotlyjs = resource_string('plotly', path).decode('utf-8')
    return plotlyjs


def js_convert(figure_or_data,outfilename, show_link=False, link_text='Export to plot.ly',
          validate=True):

    figure = tools.return_figure_from_figure_or_data(figure_or_data, validate)

    width = figure.get('layout', {}).get('width', '100%')
    height = figure.get('layout', {}).get('height', 525)
    try:
        float(width)
    except (ValueError, TypeError):
        pass
    else:
        width = str(width) + 'px'

    try:
        float(width)
    except (ValueError, TypeError):
        pass
    else:
        width = str(width) + 'px'

    plotdivid = uuid.uuid4()
    jdata = json.dumps(figure.get('data', []), cls=utils.PlotlyJSONEncoder)
    jlayout = json.dumps(figure.get('layout', {}), cls=utils.PlotlyJSONEncoder)

    config = {}
    config['showLink'] = show_link
    config['linkText'] = link_text
    config["displaylogo"]=False
    config["modeBarButtonsToRemove"]= ['sendDataToCloud']
    jconfig = json.dumps(config)

    plotly_platform_url = session.get_session_config().get('plotly_domain',
                                                           'https://plot.ly')
    if (plotly_platform_url != 'https://plot.ly' and
            link_text == 'Export to plot.ly'):

        link_domain = plotly_platform_url\
            .replace('https://', '')\
            .replace('http://', '')
        link_text = link_text.replace('plot.ly', link_domain)


    script = '\n'.join([
        'Plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{',
        '    $(".{id}.loading").remove();',
        '}})'
    ]).format(id=plotdivid,
              data=jdata,
              layout=jlayout,
              config=jconfig)

    html="""<div class="{id} loading" style="color: rgb(50,50,50);">
                 Drawing...</div>
                 <div id="{id}" style="height: {height}; width: {width};" 
                 class="plotly-graph-div">
                 </div>
                 <script type="text/javascript">
                 {script}
                 </script>
                 """.format(id=plotdivid, script=script,
                           height=height, width=width)

    #html =  html.replace('\n', '')
    with open(outfilename, 'wb') as out:
        #out.write(r'<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>')
        out.write(r'<script src="plotly-latest.min.js"></script>')
        for line in html.split('\n'):
            out.write(line)

        out.close()
    print ('JS Conversion Complete')

删除所有链接的关键行是:

^{pr2}$

您可以这样调用函数来获取一个静态HTML文件,该文件引用plotly open Source library的本地副本:

fig = {
"data": [{
    "x": [1, 2, 3],
    "y": [4, 2, 5]
}],
"layout": {
    "title": "hello world"
}
}
js_convert(fig, 'test.html')

即使是一个简单的import plotly也已经尝试连接到网络,如本例所示:

import logging
logging.basicConfig(level=logging.INFO)
import plotly

输出为:

^{pr2}$

get_graph_reference() function被调用while the graph_reference module is initialized时,就建立了连接。在

一种避免连接到plot.ly公司服务器将在~/.plotly/.config中设置无效的plotly_api_domain。对我来说,这不是一个选项,因为软件是在客户机上运行的,我不想修改他们的配置文件。另外,it is also not yet possible to change the configuration directory through an environment variable。在

一种解决方法是在绘图导入之前先执行monkey patchrequests.get

import requests
import inspect
original_get = requests.get

def plotly_no_get(*args, **kwargs):
    one_frame_up = inspect.stack()[1]
    if one_frame_up[3] == 'get_graph_reference':
        raise requests.exceptions.RequestException
    return original_get(*args, **kwargs)

requests.get = plotly_no_get
import plotly

这肯定不是一个完整的解决办法,但如果没有别的办法,这表明了这一点plot.ly公司当前不打算完全脱机运行。在

相关问题 更多 >