From 41d13c08e883588badf9d00b60c0dc24c7905fd1 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 14 May 2015 22:14:13 -0700 Subject: [PATCH 1/3] [pycaffe] correct exceptions from Python; remove PyErr_Print Previously, PyErr_Print was used to print Python exceptions. This has the side effect of clearing the exception, which results in (an additional) SystemError in the Python interpreter. Exception printing from the caffe binary tool is re-added in a future commit. --- include/caffe/python_layer.hpp | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/include/caffe/python_layer.hpp b/include/caffe/python_layer.hpp index 19cf18c9742..9c30250c1b5 100644 --- a/include/caffe/python_layer.hpp +++ b/include/caffe/python_layer.hpp @@ -18,22 +18,11 @@ class PythonLayer : public Layer { virtual void LayerSetUp(const vector*>& bottom, const vector*>& top) { - try { - self_.attr("setup")(bottom, top); - } catch (bp::error_already_set) { - PyErr_Print(); - throw; - } + self_.attr("setup")(bottom, top); } - virtual void Reshape(const vector*>& bottom, const vector*>& top) { - try { - self_.attr("reshape")(bottom, top); - } catch (bp::error_already_set) { - PyErr_Print(); - throw; - } + self_.attr("reshape")(bottom, top); } virtual inline const char* type() const { return "Python"; } @@ -41,21 +30,11 @@ class PythonLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, const vector*>& top) { - try { - self_.attr("forward")(bottom, top); - } catch (bp::error_already_set) { - PyErr_Print(); - throw; - } + self_.attr("forward")(bottom, top); } virtual void Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { - try { - self_.attr("backward")(top, propagate_down, bottom); - } catch (bp::error_already_set) { - PyErr_Print(); - throw; - } + self_.attr("backward")(top, propagate_down, bottom); } private: From cebce771309b1c07dd0fb2eb18b9b37667d955dc Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 14 May 2015 22:17:19 -0700 Subject: [PATCH 2/3] print Python exceptions when using Python layer with the caffe tool --- tools/caffe.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/caffe.cpp b/tools/caffe.cpp index 70b15f890f7..6967a46f758 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -8,6 +8,11 @@ #include "boost/algorithm/string.hpp" #include "caffe/caffe.hpp" +#ifdef WITH_PYTHON_LAYER +#include "boost/python.hpp" +namespace bp = boost::python; +#endif + using caffe::Blob; using caffe::Caffe; using caffe::Net; @@ -304,7 +309,16 @@ int main(int argc, char** argv) { // Run tool or show usage. caffe::GlobalInit(&argc, &argv); if (argc == 2) { - return GetBrewFunction(caffe::string(argv[1]))(); +#ifdef WITH_PYTHON_LAYER + try { +#endif + return GetBrewFunction(caffe::string(argv[1]))(); +#ifdef WITH_PYTHON_LAYER + } catch (bp::error_already_set) { + PyErr_Print(); + return 1; + } +#endif } else { gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/caffe"); } From 977023f171da5ff04253d413f1d2440f22dd510b Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 14 May 2015 22:20:58 -0700 Subject: [PATCH 3/3] [pytest] check that Python receives (correct) exceptions from Python layers --- python/caffe/test/test_python_layer.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/python/caffe/test/test_python_layer.py b/python/caffe/test/test_python_layer.py index 6fba49143bb..46c6e885d53 100644 --- a/python/caffe/test/test_python_layer.py +++ b/python/caffe/test/test_python_layer.py @@ -21,6 +21,13 @@ def backward(self, top, propagate_down, bottom): bottom[0].diff[...] = 10 * top[0].diff +class ExceptionLayer(caffe.Layer): + """A layer for checking exceptions from Python""" + + def setup(self, bottom, top): + raise RuntimeError + + def python_net_file(): with tempfile.NamedTemporaryFile(delete=False) as f: f.write("""name: 'pythonnet' force_backward: true @@ -34,6 +41,16 @@ def python_net_file(): return f.name +def exception_net_file(): + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write("""name: 'pythonnet' force_backward: true + input: 'data' input_shape { dim: 10 dim: 9 dim: 8 } + layer { type: 'Python' name: 'layer' bottom: 'data' top: 'top' + python_param { module: 'test_python_layer' layer: 'ExceptionLayer' } } + """) + return f.name + + class TestPythonLayer(unittest.TestCase): def setUp(self): net_file = python_net_file() @@ -61,3 +78,8 @@ def test_reshape(self): for blob in self.net.blobs.itervalues(): for d in blob.data.shape: self.assertEqual(s, d) + + def test_exception(self): + net_file = exception_net_file() + self.assertRaises(RuntimeError, caffe.Net, net_file, caffe.TEST) + os.remove(net_file)