📜  Julia 中的异常处理

📅  最后修改于: 2022-05-13 01:55:03.796000             🧑  作者: Mango

Julia 中的异常处理

在正常程序执行期间发生的任何意外情况都称为异常。 Julia 中的异常处理是一种克服这种情况的机制,方法是找出一条替代路径来继续正常的程序执行。如果不处理异常,程序会突然终止。程序不知道发生异常时要执行的操作。避免编译器在此类异常上崩溃的过程称为异常处理。

异常处理

Julia 允许通过使用 try-catch 块来处理异常。可能抛出异常的代码块放在try块中,catch块处理抛出的异常。异常通过调用堆栈传播,直到找到 try-catch 块。让我们考虑下面的代码,在这里我们尝试找到 -1 的平方根,它会抛出“DomainError”并且程序终止。

println(sqrt(-1))

输出:

ERROR: LoadError: DomainError:
sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)).
Stacktrace:
 [1] sqrt(::Int64) at ./math.jl:434
while loading /home/cg/root/945981/main.jl, in expression starting on line 1

在没有 try-catch 块的情况下,程序会突然终止。但是,我们可以通过使用 try-catch 块优雅地处理异常来防止程序终止。

println("Before Exception")
try
    sqrt(-1)
catch
    println("Cannot find the square root of negative numbers")
end
println("After Exception")

输出:

Before Exception
Cannot find the square root of negative numbers
After Exception

try-catch 块还允许将异常存储在变量中。使用catch块处理多种异常的方法称为Canonical方法。如果 x 是可索引的,则以下示例计算 x 的第三个元素的平方根,否则假定 x 是实数并返回其平方根。

sqrt_third(x) = try
        println(sqrt(x[3]))
    catch y
        if isa(y, DomainError)
            println(sqrt(complex(x[3], 0)))
        elseif isa(y, BoundsError)
            println(sqrt(x))
        end
    end
  
  
sqrt_third([1 9 16 25])
sqrt_third([1 -4 9 16])
sqrt_third(25)
sqrt_third(-9)

输出:

4.0
3.0
5.0
ERROR: LoadError: DomainError:
Stacktrace:
 [1] sqrt_third(::Int64) at /home/cg/root/945981/main.jl:7
while loading /home/cg/root/945981/main.jl, in expression starting on line 15

finally 子句的使用

无论是否发生异常,finally 块都会运行。 finally 块中的代码可用于关闭资源,如打开的文件或其他清理工作。

try
    f = open("file.txt")
catch
    println("No such file exists")
finally
    println("After exception")
end

输出:

No such file exists
After exception

抛出异常

throw()函数可用于抛出自定义异常。以下示例显示了从函数引发并由 catch 块处理的错误。 error()函数用于产生 ErrorException。

function f(x)
    if(x < 5)
        throw(error())
    end
    return sqrt(x)
end
  
try
    println(f(9))
    println(f(1))
catch e
    println("Argument less than 5")
end

输出:

3.0
Argument less than 5

异常也可以从 catch 块中抛出。 catch 块可能包含一些代码来处理捕获的异常,然后重新抛出异常。此异常必须由同一方法中的另一个 try-catch 块或调用堆栈中的任何其他方法处理。如果没有被捕获,异常会一直传播到主函数。

function f(x)
    if(x < 5)
        throw(error())
    end
    return sqrt(x)
end
  
try
    println(f(9))
    println(f(1))
catch e
    println("Argument less than 5")
    throw(error())
end

输出:

3.0
Argument less than 5
ERROR: LoadError: 
Stacktrace:
 [1] error() at ./error.jl:30
while loading /home/cg/root/945981/main.jl, in expression starting on line 13

从 catch 块中抛出错误

function f(x)
    if(x < 5)
        throw(error())
    end
    return sqrt(x)
end
  
try
    try
        println(f(9))
        println(f(1))
    catch e
        println("Argument less than 5")
        throw(error())
    end
catch e
    println("Second catch block")
end

输出:

3.0
Argument less than 5
Second catch block

一条线试接

try sqrt(x) catch y end

这意味着尝试 sqrt(x),如果抛出异常,则将其传递给变量 y。
现在如果必须返回存储在 y 中的值,那么 catch 后面必须跟一个分号。

try sqrt(x) catch; y end
try println(sqrt(-9)) catch; y end

输出:

ERROR: LoadError: UndefVarError: y not defined
while loading /home/cg/root/945981/main.jl, in expression starting on line 1

内置异常

Julia 提供了一些内置的 Exceptions,具体如下:

ExceptionDescription
ArgumentErrorThis exception is thrown when the parameters to a function call do not match a valid signature.
BoundsErrorThis exception is thrown if there the user tries to access anarray index beyond the index range.
CompositeExceptionThis exception provides information about each subtask that throws exception within a task.
DimensionMismatchThis exception is thrown when objects called do not have matching dimensionality.
DivideErrorThis exception is thrown when the user tries to divide by 0(zero).
DomainErrorThis exception is thrown when the argument to a function or constructor does not lie in the valid domain.
EOFErrorThis exception is thrown when there is no more data left to read in a file.
ErrorExceptionThis exception is thrown to indicate generic error.
InexactErrorThis exception is thrown when the program cannot exactly convert a particular value to type T in a method.
InitErrorThis exception is thrown when an error occurs while running __init__ function of a module.
InterruptExceptionThis exception is thrown when a process is stopped from the terminal using CTRL+C .
InvalidStateExceptionThis exception is thrown when the program runs into an invalid state.
KeyErrorThis exception is thrown when when a user tries to access or delete a non-existing element from AbstractDict or Set.
LoadErrorThis exception is thrown if an error occurs while importing or using a file.
OutOfMemoryErrorThis exception is thrown when a program exceeds the available system memory.
ReadOnlyMemoryErrorThis exception is thrown when a program tries to write a memory that is read-only.
RemoteExceptionThis exception is thrown when exception of a remote computer is thrown locally. The exception specifies the pid of the worker and the corresponding exception.
MethodErrorThis exception is thrown when a method with the required type signature does not exist.
OverflowErrorThis exception is thrown when result of an expression is too large for the specified type and causes a wrap-around.
Meta.ParseErrorThis exception is thrown when an expression passed to the parse function cannot be interpreted as a valid Julia expression.
SystemErrorThis exception is thrown when a system call fails.
TypeErrorThis exception is thrown when a type assertion fails, or an intrinsic function is called with incorrect argument type.
UndefRefErrorThis exception is thrown if an item or field is not defined for the specified object.
UndefVarErrorThis exception is thrown when a symbol is not defined in the current scope.
StringIndexErrorThis exception is thrown when the user tries to access a string index that exceeds the string length.