按照您的建议,可能有一些方法可以使用 svg 和一些 javascript 或 pdf 工具提示(在您提到它们之前我不知道存在 pdf 工具提示!)。
顺便说一句,我应该花点时间提到mpld3,它使用d3 将matplotlib 图形重新创建为javascript 可视化。它确实允许非常可共享的交互式图形,并提供了一些制作交互式工具提示的示例。
但是,我不确定如何使 matplotlib 的 svg 文件具有一般交互性,并且您提到您不想走 javascript 路线,所以我将引导您构建一个“独立”可执行文件(或者,更确切地说,一个包含可执行文件和相关库的目录)。
使用cx_freeze 和matplotlib 构建“独立”可执行文件
至少在打包可执行文件方面,我推荐cx_freeze。还有很多其他选项(例如pyinstaller、py2exe、py2app 等),但其中大多数都是特定于平台的,对我的口味来说有点“神奇”。 cx_freeze 需要更多的知识才能使用,但它非常可靠,一旦您知道需要包含哪些内容,使用起来也不会太难。
首先,我将向您介绍的完整示例可在此处获得:https://gist.github.com/joferkington/9214844 它使用您在之前的问题中提供的示例脚本和数据。
关键是构建一个setup.py 文件,该文件正确引用 1) matplotlib 的数据文件和 2) 您需要包含在代码中以使其正确运行的任何数据。
之后,就像python setup.py build_exe 一样简单,然后将它创建的构建目录 tar 发送给其他人。 (您可能想做一些更花哨的事情。可以制作包含 tar 数据、库和可执行文件的 shell 脚本,但我将在此处跳过该部分。)
制作setup.py 文件
使用setup.py。假设您有一个名为 plot.py 的简单脚本,其中包含一些基本的绘图代码和一个名为 data.csv 的文件,其中包含您要使用 matplotlib 绘制的数据等。setup.py 文件为 cx_freeze 看起来像这样的东西:(另外,为简单起见,我假设您将 Tk 后端用于 matplotlib。如果您不使用,情况看起来会略有不同。)
import cx_Freeze
import sys
import matplotlib
base = None
if sys.platform == "win32":
base = "Win32GUI"
executables = [
cx_Freeze.Executable("plot.py", base = base),
]
build_exe_options = {"includes":["matplotlib.backends.backend_tkagg"],
"include_files":[(matplotlib.get_data_path(), "mpl-data"),
('data.csv', 'data.csv')],
"excludes":[],
}
cx_Freeze.setup(
name = "script",
options = {"build_exe": build_exe_options},
version = "0.0",
description = "A basic example",
executables = executables)
其中大部分是样板文件。关键部分是:
- 脚本的名称 (
x_Freeze.Executable("plot.py", base = base))
-
build_exe_options 中的"includes" 部分。 cx_freeze 将尝试自动猜测它需要包含哪些模块,但在某些情况下无法检测到它需要的所有模块。本节允许您指定要显式包含的其他模块。 matplotlib 后端通常无法正确自动检测,因此您需要明确包含您正在使用的任何后端。
-
build_exe_options 中的"include_files" 部分。这表示需要包含的任何其他数据文件。 Matplotlib 有一些数据文件(图标等)需要与代码和库一起提供才能正常运行。 (matplotlib.get_data_path(), "mpl-data") 行获取这些文件并将它们放在构建目录中名为“mpl-data”的文件夹中。同样,('data.csv', 'data.csv') 行获取您的“data.csv”文件并将其以相同的名称保存在构建目录中。
我会花一点时间来提一下"excludes" 选项。这完全是可选的,但cx_freeze 通常会包含许多脚本运行实际上并不需要的库。如果您想缩小要分发的文件的大小,您可能需要在此处列出要排除的特定 python 模块。 (例如"excludes":['PyQt4', 'scipy'])
其余的都是不言自明的。您可能需要填写描述、版本等,但构建可执行文件不需要。
建筑
所以此时,我们有一个目录,内容类似如下:
$ ls
data.csv plot.py setup.py
data.csv 有我们的数据,plot.py 是绘制它的脚本,setup.py 如上所述。
要构建一个可执行文件,我们会运行
python setup.py build_exe
您会得到一个很长的构建日志以及它正在复制的确切内容(可能还有一些在大多数情况下可以安全忽略的警告)。 (这是调试setup.py 文件问题的有用信息。)
完成后,您会注意到一个名为 build 的新目录。
$ ls
build data.csv plot.py setup.py
此时,build 将包含一个目录,其名称类似于:
$ ls build
exe.linux-x86_64-2.7
exe.whatever 目录包含库、数据和可执行文件,您需要将它们分发给人们以使事情正常运行。
要查看它是否有效,请尝试(注意目录中的显式cd!稍后会详细介绍。):
$ cd build/exe.linux-x86_64-2.7
$ ./plot
(很明显,如果你上面的文件没有被称为plot.py,那么可执行文件就不会被称为plot,但你明白了。)
此时,您可以将 exe.whatever 目录 tar (可能希望在 tar 之前重命名它),将其发送出去,然后通过解压缩并调用 cd name_of_dir; ./plot 来告诉人们运行它。
关于数据路径的注意事项
我提到我们目前需要在运行之前明确地将cd 放入目录中。这纯粹是因为plot.py 在当前目录中寻找一个名为data.csv 的文件。
换句话说,plot.py 中有一行:
df = pd.read_csv('data.csv', ...)
我们使setup.py 足够聪明,可以包含data.csv,但读取它的代码预计它位于当前目录中。
你有两个选择:
- 在运行脚本之前始终将
cd 放入目录中(实际上,发送一个简短的脚本,cds 进入,运行程序,cds 退出)。如果您不想为第二个选项烦恼,这可作为最后的手段。
- 更改代码以引用相对于脚本位置的数据文件。
出于多种原因,第二个选项更好,但您必须稍微修改您的脚本(在本例中为plot.py)。
通常,您会使用__file__ 的路径来确定相对于脚本本身的位置。但是,使用cx_freeze,__file__ 将不会被定义,而您想要的路径是sys.executable 的路径。因此,您通常会这样做:(来自 cx_freeze 常见问题解答:http://cx-freeze.readthedocs.org/en/latest/faq.html#data-files)
def find_data_file(filename):
if getattr(sys, 'frozen', False):
# The application is frozen
datadir = os.path.dirname(sys.executable)
else:
# The application is not frozen
# Change this bit to match where you store your data files:
datadir = os.path.dirname(__file__)
return os.path.join(datadir, filename)
在这种情况下,您将修改您的代码:
pd.read_csv('data.csv', ...)
要做的事情:
pd.read_csv(find_data_file('data.csv'), ...)
相反。 (这在 gist I linked to originally 中的 plot.py 文件中尚未完成。我将把它留给读者作为练习。)
完成后,无论当前工作目录是什么,您都可以直接调用/path/to/where/the/directory/gets/copied/plot。
分发
我不会在这个话题上说太多。有很多方法可以处理这个问题。使用cx_freeze,您将发送一个包含库和单个可执行文件的文件夹。
在最简单的情况下,您只需将其 tar,然后告诉人们解压缩并运行 where/they/extracted/it/name_of_the_execuctable。您可能希望将文件夹从 exe.linux-x86_64-2.7 重命名为类似于 my_package 的名称,并包含一个名为 run_this 的 shell 脚本或其他名称,但这取决于您。
在其他情况下,您可能想要编写一个包装脚本,甚至是一个.desktop 文件。桌面文件必须有绝对路径,所以在这种情况下你需要做更多的事情。通常,您编写某种安装程序脚本,修改 whatever.desktop 以指向您的程序安装位置的绝对路径。
可以将压缩后的数据、库和可执行文件嵌入到“自解压”安装脚本中。如果您想四处寻找它们,则网络上有一些示例。您还可以构建一个 .rpm 或 .deb。同样,我将跳过详细的示例,让您自己弄清楚。
总体而言,对于您似乎正在做的事情,发送 tarball 和 README 可能是最简单的途径。