Skip to content

Commit

Permalink
[SPARK-19505][PYTHON] AttributeError on Exception.message in Python3
Browse files Browse the repository at this point in the history
## What changes were proposed in this pull request?

Added `util._message_exception` helper to use `str(e)` when `e.message` is unavailable (Python3).  Grepped for all occurrences of `.message` in `pyspark/` and these were the only occurrences.

## How was this patch tested?

- Doctests for helper function

## Legal

This is my original work and I license the work to the project under the project’s open source license.

Author: David Gingrich <david@textio.com>

Closes #16845 from dgingrich/topic-spark-19505-py3-exceptions.
  • Loading branch information
David Gingrich authored and holdenk committed Apr 11, 2017
1 parent 123b4fb commit 6297697
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 5 deletions.
1 change: 1 addition & 0 deletions dev/sparktestsupport/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ def __hash__(self):
"pyspark.profiler",
"pyspark.shuffle",
"pyspark.tests",
"pyspark.util",
]
)

Expand Down
4 changes: 3 additions & 1 deletion python/pyspark/broadcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from tempfile import NamedTemporaryFile

from pyspark.cloudpickle import print_exec
from pyspark.util import _exception_message

if sys.version < '3':
import cPickle as pickle
Expand Down Expand Up @@ -82,7 +83,8 @@ def dump(self, value, f):
except pickle.PickleError:
raise
except Exception as e:
msg = "Could not serialize broadcast: " + e.__class__.__name__ + ": " + e.message
msg = "Could not serialize broadcast: %s: %s" \
% (e.__class__.__name__, _exception_message(e))
print_exec(sys.stderr)
raise pickle.PicklingError(msg)
f.close()
Expand Down
9 changes: 5 additions & 4 deletions python/pyspark/cloudpickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import traceback
import weakref

from pyspark.util import _exception_message

if sys.version < '3':
from pickle import Pickler
Expand Down Expand Up @@ -152,13 +153,13 @@ def dump(self, obj):
except pickle.PickleError:
raise
except Exception as e:
if "'i' format requires" in e.message:
msg = "Object too large to serialize: " + e.message
emsg = _exception_message(e)
if "'i' format requires" in emsg:
msg = "Object too large to serialize: %s" % emsg
else:
msg = "Could not serialize object: " + e.__class__.__name__ + ": " + e.message
msg = "Could not serialize object: %s: %s" % (e.__class__.__name__, emsg)
print_exec(sys.stderr)
raise pickle.PicklingError(msg)


def save_memoryview(self, obj):
"""Fallback to save_string"""
Expand Down
45 changes: 45 additions & 0 deletions python/pyspark/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

__all__ = []


def _exception_message(excp):
"""Return the message from an exception as either a str or unicode object. Supports both
Python 2 and Python 3.
>>> msg = "Exception message"
>>> excp = Exception(msg)
>>> msg == _exception_message(excp)
True
>>> msg = u"unicöde"
>>> excp = Exception(msg)
>>> msg == _exception_message(excp)
True
"""
if hasattr(excp, "message"):
return excp.message
return str(excp)


if __name__ == "__main__":
import doctest
(failure_count, test_count) = doctest.testmod()
if failure_count:
exit(-1)

0 comments on commit 6297697

Please sign in to comment.