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

禁止Python中的Plotly以任何形式与网络通信,python,networking,plotly,Python,Networking,Plotly,Plotly(从Python内部使用)是“严格本地”的吗?换句话说,是否有可能以一种保证它不会因任何原因与网络联系的方式使用它 这包括程序尝试联系Plotly服务(因为这是业务模式)以及确保在生成的html中单击任何位置都不会有指向Plotly或其他任何位置的链接 当然,我希望能够在连接到网络的生产机器上执行此操作,因此拔出网络连接不是一个选项。我想我已经想出了一个解决方案。首先,您需要下载开源的Plotly.js。然后我有一个函数,写在下面,它将从python绘图中生成javascript,并

Plotly(从Python内部使用)是“严格本地”的吗?换句话说,是否有可能以一种保证它不会因任何原因与网络联系的方式使用它

这包括程序尝试联系Plotly服务(因为这是业务模式)以及确保在生成的html中单击任何位置都不会有指向Plotly或其他任何位置的链接


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

我想我已经想出了一个解决方案。首先,您需要下载开源的Plotly.js。然后我有一个函数,写在下面,它将从python绘图中生成javascript,并引用您的本地plotly-latest.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')
您可以这样调用函数以获取引用您的本地plotly open source library副本的静态HTML文件:

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
输出为:

INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): api.plot.ly
在调用时建立连接

避免连接到plot.ly服务器的一种方法是在
~/.plotly/.config
中设置无效的
plotly\u api\u域。对我来说,这不是一个选项,因为软件在客户机上运行,我不想修改他们的配置文件。另外

一种解决方法是对请求进行monkey patch
操作。在以绘图方式导入之前获取

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目前不打算完全脱机运行。

我还没有做任何广泛的测试,但它看起来像plot.ly提供了“脱机”模式:

一个简单的例子:

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

plot([Scatter(x=[1, 2, 3], y=[3, 1, 6])])
您可以通过
pip
安装Plot.ly,然后运行上述脚本以生成静态HTML文件:

$ pip install plotly
$ python ./above_script.py
当我从终端运行此操作时,我的web浏览器将打开到以下文件URL:

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

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

谢谢,这很有帮助。我问这个问题的主要目的是看看是否有一个内置的API来避免任何网络通信,或者甚至是一个“关闭网络访问”机制,例如,不导入一个模块来执行网络通信。原因是为了确保机密数据不会泄露。你的答案提供了一种让它与本地链接一起工作的方法,这是有价值的,但并不能保证。你找到更好的解决方案了吗?@LauriK,目前还没有。
file:///some/path/to/temp-plot.html