cx_Oracle
数据库启动时,以下代码可以正常工作:
#!C:\Python27
import cx_Oracle
try:
conn = cx_Oracle.connect("scott/tiger@oracle")
try:
curs = conn.cursor()
curs.execute("SELECT dummy FROM sys.dual")
print curs.fetchone()[0]
finally:
curs.close()
finally:
conn.close()
Run Code Online (Sandbox Code Playgroud)
但是,如果在运行此脚本时数据库发生故障,NameError
则会引发a:
Traceback (most recent call last):
File "C:\Users\ArtMetzer\Documents\Code\Python\db_conn_test.py", line 14, in <module>
conn.close()
NameError: name 'conn' is not defined
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义: cx_Oracle
无法实例化连接,因此变量conn
永远不会被设置,因此没有close()
方法.
在Python中,什么是确保数据库连接关闭的最佳方法,同时仍然优雅地处理down数据库的条件?
做类似以下的事情对我来说似乎是一个巨大的障碍:
finally:
try:
conn.close()
except NameError:
pass
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法来确保当我完成它时,在堆上执行的对象总是被释放.
我知道如果它被分配在堆栈上,我可以使用RAII来确保它将被处理 - 不幸的是,这对我(至少直接)不起作用,因为有问题的对象实际上是通过调用api函数创建的然后返回指向它在堆上创建的对象的指针.
所以,从概念上讲,我想做的是:
TheApi::ApiObject* p_myObj = TheApi::createAnApiObj();
try
{
doStuffWithMyObjThatMayError(p_myObj);
}
finally
{
delete p_myObj;
}
Run Code Online (Sandbox Code Playgroud)
我唯一能想到的就是创建一些虚拟清理类,并在堆栈上创建一个实例:
class MegaMaid
{
private:
TheApi::ApiObject* toFree;
public:
MegaMaid(TheApi::ApiObject* toFree)
{
this->toFree = toFree;
}
~MegaMaid()
{
delete toFree;
}
};
void doStuff()
{
TheApi::ApiObject* p_myObj = TheApi::createAnApiObj();
TheApi::ApiObject* p_myObj;
MegaMaid cleaner(p_myObj);
doStuffWithMyObjThatMayError(p_myObj);
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现这一目标?或者这是公认的解决方案吗?
在C#.NET中,我们来看以下示例
[WebMethod]
public int TakeAction()
{
try {
//Call method A
Return 1;
} catch (Exception e) {
//Call method B
Return 0;
} finally {
//Call method C
}
}
Run Code Online (Sandbox Code Playgroud)
现在让我们说方法C是一个长期运行的过程.
在调用方法C之前,或在调用/完成方法之后,调用TakeAction的客户端是否返回返回值?
在我的项目中,我有一个构造函数可以抛出的对象.所以我正在使用的代码如下:
MyObject obj = null;
try
{
obj = new MyObject();
obj.DoSomething();
}
finally
{
if (obj != null)
obj.Free();
}
Run Code Online (Sandbox Code Playgroud)
using (MyObject obj = new MyObject())
{
obj.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
由.NET CLR转换为
{
MyObject obj = new MyObject();
try
{
obj.DoSomething();
}
finally
{
if (obj != null)
((IDisposable)obj).Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是:我可以以某种方式使CLR将对象的构造函数放入try块中吗?
我有一些代码创建了一个JarFile
和一个URLClassLoader
,我想在最后关闭它们.当然,我决定使用该finally
块来处理清理:
JarFile jar = ...;
URLClassLoader loader = ...;
try {
// work ...
} finally {
jar.close();
loader.close();
}
Run Code Online (Sandbox Code Playgroud)
但是,两个close()
调用都可以抛出异常,因此如果jar.close()
抛出异常,则loader.close()
无法访问.我想解决这个问题的一种方法是jar.close()
使用try-catch块进行处理:
JarFile jar = ...;
URLClassLoader loader = ...;
try {
// work ...
} finally {
try {
jar.close();
} catch(IOException e) {
}
loader.close();
}
Run Code Online (Sandbox Code Playgroud)
但这看起来很丑陋而且过分.是否有一种优雅的方法来处理finally
块中与清理相关的异常?
我已经看到这种模式现在在几个不同的地方使用,但我不确定它到底是什么或为什么需要它.鉴于我已经在优质项目中看到它,我确信它很有用,但我想理解它,而不是盲目地遵循它.我在Servlet过滤器和Struts2拦截器中特别看到了这种模式(在概念上与过滤器非常相似).
以下是Google Guice(Servlet)3.0的示例:
Context previous = localContext.get();
try {
localContext.set(new Context((HttpServletRequest) servletRequest,
(HttpServletResponse) servletResponse));
//dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored
filterPipeline.dispatch(servletRequest, servletResponse, filterChain);
} finally {
localContext.set(previous);
}
Run Code Online (Sandbox Code Playgroud)
恢复finally块中的值有什么需要或好处?
可能重复:
else的目的,最后是异常处理
我想理解为什么声明中finally
存在该条款try/except
.我理解它的作用,但很明显,如果它在语言中占有一席之地,我会遗漏一些东西.具体来说,在finally
字段中编写一个子句与在try/except
语句之外写一个子句之间的区别是什么?
假设有这样一个类:
class A {
private:
QFile file;
public:
A::A(QFile file): file(file) {}
void doSomething() {
file.open(QIODevice::WriteOnly);
// ... do operations that can throw an exception
file.close();
}
}
Run Code Online (Sandbox Code Playgroud)
如果发生某些事情, close() 永远不会调用它。正确的方法是使用 try - finally,但 C++ 不支持它:
class A {
private:
QFile file;
public:
A::A(QFile file): file(file) {}
void doSomething() {
file.open(QIODevice::WriteOnly);
try {
// ... do operations that can throw an exception
}
finally {
file.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能在C++上做到这一点?
请考虑以下代码:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
Run Code Online (Sandbox Code Playgroud)
为了执行一些最终操作,需要额外的变量.将其写为:
try {
return array[index];
} finally {
index = (index + 1) % array.length;
}
Run Code Online (Sandbox Code Playgroud)
还是会对绩效产生影响?一般来说,它被认为是一种好/坏的做法,如果是这样,为什么呢?
(在示例中,假设它index
是一个有效的索引,array
并且代码不会抛出ArrayIndexOutOfBoundsException
)
编辑:问题不是关于需要使用try-finally
,而是关于我选择做的任何性能上的获得或损失.没有它,就会创建一个变量.有了它,返回的值可能以更有效的方式存储在其他地方.
很长一段时间,我认为它可以让我释放finally
块中的所有资源,并且我认为如果try
块中发生异常,那么该块中的资源仍然会被释放finally
。但情况似乎并非如此。
我有以下一段代码:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
Run Code Online (Sandbox Code Playgroud)
我从来没有到达打印到控制台的行。这意味着finally
在这种情况下,我将无法在块内抛出异常时释放块中的资源try
。
所以,我相信有两件事:要么我遗漏了什么,要么try
+finally
组合在 C# 中没有用例。第二个语句是有道理的,因为我将获得与上面的代码和下面的代码产生的相同的功能:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the …
Run Code Online (Sandbox Code Playgroud)