使用Bazel运行TensorFlow时,如何配置.pb图文件路径?
首先得把问题根源理清楚:当你用bazel run执行目标时,Bazel默认的工作目录是你的项目根目录(也就是~/tensorflow/),而非bazel-bin/tensorflow/cc/dnnops/。所以你代码里用相对路径"graph.pb"时,程序会去项目根目录找这个文件,哪怕你把pb复制到bazel-bin的对应路径也没用——因为运行时的工作目录根本不在那。
下面给你几个实用的解决方案:
方案1:修改BUILD文件,将pb文件作为依赖打包(推荐)
这是最贴合Bazel工作流的做法,让Bazel自动帮你管理文件路径。在~/tensorflow/tensorflow/cc/dnnops/BUILD文件里,给cc_binary规则添加data属性,把graph.pb列为依赖:
cc_binary( name = "dnnops", srcs = ["main.cc"], # 新增这一行,告诉Bazel要把这个文件打包到运行环境中 data = ["graph.pb"], # 保留你原有的依赖配置 deps = [ "//tensorflow/core:lib", # 其他你的依赖项... ], )
修改完成后,直接用bazel run //tensorflow/cc/dnnops:dnnops运行程序即可。Bazel会自动把graph.pb复制到程序运行时能找到的路径,你代码里的ReadBinaryProto(tf::Env::Default(), "graph.pb", &graph_def)就能正常读取文件了。
方案2:在代码中动态获取正确的文件路径
如果不想修改BUILD文件,你可以通过代码获取当前可执行文件的位置,再拼接出pb文件的路径。利用TensorFlow提供的路径工具类就能轻松实现:
#include "tensorflow/core/platform/env.h" #include "tensorflow/core/platform/path.h" // ... std::string exe_path; // 获取当前可执行文件的绝对路径 TF_CHECK_OK(tf::Env::Default()->GetExecutablePath(&exe_path)); // 拼接出pb文件的路径:可执行文件所在目录 + graph.pb std::string pb_path = tf::io::JoinPath(tf::io::Dirname(exe_path), "graph.pb"); // 用拼接好的路径读取文件 status = ReadBinaryProto(tf::Env::Default(), pb_path, &graph_def);
这样不管你在哪运行程序,都能精准定位到pb文件。
方案3:运行时指定绝对路径(临时测试方案)
如果你只是想快速验证功能,可以直接在代码里写pb文件的绝对路径,比如:
status = ReadBinaryProto(tf::Env::Default(), "/home/your-username/tensorflow/tensorflow/cc/dnnops/graph.pb", &graph_def);
或者运行程序时通过命令行参数传入路径,代码里读取参数来获取pb路径——不过这种方式灵活性差,不推荐长期使用。
补充:为什么复制pb到bazel-bin目录没用?
当你直接进入bazel-bin/tensorflow/cc/dnnops/目录运行./dnnops时,相对路径graph.pb会指向当前目录,这时候复制过去是有效的;但用bazel run命令时,Bazel会切换到项目根目录执行程序,所以程序找的是~/tensorflow/graph.pb,而非bazel-bin下的那个文件。
内容的提问来源于stack exchange,提问作者bobuntu

