我正在尝试使用 cx_Oracle 连接到 Oracle 实例并执行一些 DDL 语句:
db = None
try:
db = cx_Oracle.connect('username', 'password', 'hostname:port/SERVICENAME')
#print(db.version)
except cx_Oracle.DatabaseError as e:
error, = e.args
if error.code == 1017:
print('Please check your credentials.')
# sys.exit()?
else:
print('Database connection error: %s'.format(e))
cursor = db.cursor()
try:
cursor.execute(ddl_statements)
except cx_Oracle.DatabaseError as e:
error, = e.args
if error.code == 955:
print('Table already exists')
if error.code == 1031:
print("Insufficient privileges - are you sure you're using the owner account?")
print(error.code)
print(error.message)
print(error.context)
cursor.close()
db.commit()
db.close()
但是,我不太确定这里异常处理的最佳设计是什么。
首先,我在 try block 中创建 db 对象,以捕获任何连接错误。
但是,如果它无法连接,那么 db 将不再存在 - 这就是我在上面设置 db = None 的原因。但是,这是好的做法吗?
理想情况下,我需要捕获连接错误,然后是运行 DDL 语句的错误,等等。
嵌套异常是个好主意吗?或者有没有更好的方法来处理这样的依赖/级联异常?
此外,我希望脚本在某些部分(例如连接失败)中终止 - 因此注释掉了 sys.exit() 调用。但是,我听说像这样对流控制使用异常处理是不好的做法。想法?
最佳答案
However, if it can't connect, then
dbwon't exist further down - which is why I setdb = Noneabove. However, is that good practice?
不,设置 db = None 不是最佳做法。有两种可能,要么连接到数据库,要么不连接。
连接数据库不起作用:
由于引发的异常已被捕获且未重新引发,因此您将继续直到到达 cursor = db.Cursor()。
db == None,因此,将引发类似于 TypeError: 'NoneType' object has no attribute 'Cursor' 的异常。由于数据库连接失败时产生的异常已经被捕获,所以失败的原因是伪装的。
就个人而言,除非您很快再试一次,否则我总是会引发连接异常。如何捕捉它取决于你;如果错误仍然存在,我会通过电子邮件说“去检查数据库”。
连接到数据库确实有效:
变量 db 在您的 try:... except block 中分配。如果 connect 方法确实有效,则 db 将替换为连接对象。
无论哪种方式,db 的初始值都不会被使用。
However, I've heard that using exception handling for flow control like this is bad practice.
与其他语言不同,Python 确实使用异常处理来进行流控制。在我的回答结束时,我已经链接到 Stack Overflow 和 Programmers 上提出类似问题的几个问题。在每个示例中,您都会看到“但在 Python 中”的字样。
这并不是说你应该过火,但 Python 通常使用 EAFP , “请求宽恕比请求许可更容易。” How do I check if a variable exists? 中投票的前三名示例是如何同时使用流量控制的好例子。
Is nesting exceptions a good idea? Or is there a better way of dealing with dependent/cascaded exceptions like this?
嵌套异常并没有什么问题,只要您理智地执行此操作即可。考虑你的代码。您可以删除所有异常并将整个事物包装在 try:... except block 中。如果引发了异常,那么您就会知道它是什么,但是要准确找出问题所在就有点困难了。
如果您想在 cursor.execute 失败时向自己发送电子邮件,会发生什么?为了执行这项任务,您应该在 cursor.execute 周围有一个异常(exception)。然后你重新引发异常,让它在你的外部 try:... 中被捕获。不重新引发将导致您的代码继续执行,就好像什么都没发生一样,并且您在外部 try:... 中放置的用于处理异常的任何逻辑都将被忽略。
最终所有的异常都继承自 BaseException .
Also, there are some parts (e.g. connection failures) where I'd like the script to just terminate - hence the commented out sys.exit() call.
我添加了一个简单的类以及如何调用它,这大致就是我将如何做你想做的事情。如果这要在后台运行,那么打印错误是不值得的——人们不会坐在那里手动寻找错误。他们应该以您的标准方式登录,并通知适当的人。出于这个原因,我删除了打印并替换为记录提醒。
当 connect 方法失败并引发异常时,我已将类拆分为多个函数,因此 execute 调用将不会运行并且脚本将完成,尝试断开连接后。
import cx_Oracle
class Oracle(object):
def connect(self, username, password, hostname, port, servicename):
""" Connect to the database. """
try:
self.db = cx_Oracle.connect(username, password
, hostname + ':' + port + '/' + servicename)
except cx_Oracle.DatabaseError as e:
# Log error as appropriate
raise
# If the database connection succeeded create the cursor
# we-re going to use.
self.cursor = self.db.cursor()
def disconnect(self):
"""
Disconnect from the database. If this fails, for instance
if the connection instance doesn't exist, ignore the exception.
"""
try:
self.cursor.close()
self.db.close()
except cx_Oracle.DatabaseError:
pass
def execute(self, sql, bindvars=None, commit=False):
"""
Execute whatever SQL statements are passed to the method;
commit if specified. Do not specify fetchall() in here as
the SQL statement may not be a select.
bindvars is a dictionary of variables you pass to execute.
"""
try:
self.cursor.execute(sql, bindvars)
except cx_Oracle.DatabaseError as e:
# Log error as appropriate
raise
# Only commit if it-s necessary.
if commit:
self.db.commit()
然后调用它:
if __name__ == "__main__":
oracle = Oracle.connect('username', 'password', 'hostname'
, 'port', 'servicename')
try:
# No commit as you don-t need to commit DDL.
oracle.execute('ddl_statements')
# Ensure that we always disconnect from the database to avoid
# ORA-00018: Maximum number of sessions exceeded.
finally:
oracle.disconnect()
延伸阅读:
Why not use exceptions as regular flow of control?
Is python exception handling more efficient than PHP and/or other languages?
Arguments for or against using try catch as logical operators
关于python - cx_Oracle 和异常处理 - 好的做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7465889/
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决