diff --git a/src/Hython/ExceptionHandling.hs b/src/Hython/ExceptionHandling.hs
index 18d1bb6..aa025af 100644
--- a/src/Hython/ExceptionHandling.hs
+++ b/src/Hython/ExceptionHandling.hs
@@ -3,29 +3,44 @@ where
 
 import Control.Monad.Cont.Class (MonadCont)
 import Data.Text (Text)
+import qualified Data.Text as T
 
 import Hython.Call (call)
+import Hython.Class (isSubClass)
 import Hython.ControlFlow (getExceptionHandler, setCurrentException)
 import Hython.Environment (MonadEnv, lookupName)
-import Hython.Types (MonadInterpreter, newString, Object)
+import Hython.Types hiding (raise)
 import qualified Hython.Types as Types
 
-raise :: MonadInterpreter m => Object -> m ()
-raise exception = do
-    handler <- getExceptionHandler
 
-    setCurrentException exception
-    handler exception
+raiseOr :: (MonadEnv Object m, MonadInterpreter m) => m () -> Object -> m ()
+raiseOr raiseError exc@(Object objectInfo) = do
+    mBaseClass <- lookupName (T.pack "BaseException")
+    case mBaseClass of
+        Just (Class baseClassInfo) ->
+            if isSubClass (objectClass objectInfo) baseClassInfo
+                then do
+                    handler <- getExceptionHandler
+                    setCurrentException exc
+                    handler exc
+                else raiseError
+        _ -> Types.raise "SystemError" "could not find BaseException class"
+raiseOr raiseError _ = raiseError
+
+raiseExternal :: (MonadEnv Object m, MonadInterpreter m) => Object -> m ()
+raiseExternal =
+    raiseOr $ Types.raise "TypeError" "exceptions must derive from BaseException"
 
 raiseInternal :: (MonadCont m, MonadEnv Object m, MonadInterpreter m) => Text -> Text -> m ()
 raiseInternal clsName description = do
     mcls <- lookupName clsName
     case mcls of
-        Just obj    -> do
+        Just cls@(Types.Class _) -> do
             descriptionStr  <- newString description
-            exception       <- call obj [descriptionStr] []
-            raise exception
-        _           -> Types.raise "TypeError" "exceptions must derive from BaseException"
-
-
+            exception       <- call cls [descriptionStr] []
+            raiseOr raiseError exception
+        _ -> raiseError
+  where
+    raiseError = Types.raise "SystemError" ("internally raised invalid exception "
+                     ++ T.unpack clsName ++ "(\"" ++ T.unpack description ++ "\")")
 
diff --git a/src/Hython/Interpreter.hs b/src/Hython/Interpreter.hs
index 83a6ef0..62430c8 100644
--- a/src/Hython/Interpreter.hs
+++ b/src/Hython/Interpreter.hs
@@ -118,7 +118,7 @@ defaultExceptionHandler ex = do
                 putStr . T.unpack . className . objectClass $ info
                 putStr ": "
                 putStrLn msg
-        _ -> liftIO $ putStrLn "o_O: raised a non-object exception"
+        _ -> liftIO $ putStrLn "SystemError: uncaught non-object exception"
 
     liftIO exitFailure
 
diff --git a/src/Hython/Statement.hs b/src/Hython/Statement.hs
index 84a96e3..2c5c33b 100644
--- a/src/Hython/Statement.hs
+++ b/src/Hython/Statement.hs
@@ -17,9 +17,10 @@ import qualified Data.Text as T
 import Language.Python
 
 import Hython.Builtins (isInstance, len, setAttr)
+import Hython.Class (isSubClass)
 import Hython.ControlFlow
 import Hython.Environment
-import qualified Hython.ExceptionHandling as EH
+import Hython.ExceptionHandling (raiseExternal)
 import Hython.Expression (evalExpr, evalParam)
 import qualified Hython.Module as Module
 import Hython.Ref
@@ -173,7 +174,7 @@ eval (Nonlocal names) = mapM_ bindNonlocal names
 
 eval (Pass) = return ()
 
-eval (Raise expr _from) = EH.raise =<< evalExpr expr
+eval (Raise expr _from) = raiseExternal =<< evalExpr expr
 
 eval (Reraise) = do
     mexception  <- getCurrentException
@@ -201,13 +202,14 @@ eval (Try clauses block elseBlock finallyBlock) = do
     -- Evaluate exception handler clauses
     handlers <- forM clauses $ \(ExceptClause expr name handlerBlock) -> do
         mcls <- evalExpr expr
-        case mcls of
-            (Class cls) -> return . Just $ ExceptionHandler name cls handlerBlock
-            _           -> do
-                raise "SyntaxError" "invalid class in except block header"
+        mBaseClass <- lookupName (T.pack "BaseException")
+        case (mcls, mBaseClass) of
+            (Class cls, Just (Class baseClass)) | isSubClass cls baseClass ->
+                return . Just $ ExceptionHandler name cls handlerBlock
+            _ -> do
+                raise "TypeError" "catching classes that do not inherit from BaseException is not allowed"
                 return Nothing
 
-    --
     exception <- callCC $ \handler -> do
         setExceptionHandler handler
 
diff --git a/test/control/exception.py b/test/control/exception.py
index 90d0d3d..435bb3a 100644
--- a/test/control/exception.py
+++ b/test/control/exception.py
@@ -263,8 +263,7 @@ def test_finally_block_raises_exception():
 try:
     raise Exception("test")
 except Exception as e:
-    if e != None:           # Test that e exists since we don't implement __str__
-        print("Exists!")
+    print(e)
 
 # Test that the correct handler is located, even if it exists in outer scopes
 def test_caught_by_outside_handlers():
@@ -341,3 +340,30 @@ def test_return_in_while():
     print(test_return_in_while())
 finally:
     print("OK!")
+
+# Test that only objects can be raised
+try:
+    raise 3
+except TypeError as e:
+    print("TypeError1")
+
+# Test that only classes derived from BaseException can be raised
+class T:
+    def __str__(self):
+        return "T"
+
+try:
+    raise T("e")
+except TypeError:
+    print("TypeError2")
+
+# Test that only classes derived from BaseException can be caught
+try:
+    try:
+        raise Exception("test")
+    except T:
+        pass
+except TypeError:
+    print("TypeError3")
+except:
+    print("caught something else")