I'm trying to use python 2.7.5 in a c/c++ DLL. This DLL is used by another application which has made debugging a challenge. After banging away at this for hours I have isolated the problem down to where a file read in a 'with' statement is throwing an exception. This I do not understand...'with' should absorb an exception if implemented correctly, right? Anyway calling the same python code from the command line has no problems at all.
我正在尝试在c / c ++ DLL中使用python 2.7.5。此DLL由另一个使调试成为挑战的应用程序使用。在敲了几个小时之后,我把问题分离到了'with'语句中读取的文件抛出异常的地方。我不明白......如果正确实施,'with'应该吸收异常,对吧?无论如何从命令行调用相同的python代码都没有问题。
My C/CPP DLL calls this...
我的C / CPP DLL调用这个...
def parsetest(filename):
bytesin = getMD3Bytes(filename)
return bytesin
def getMD3Bytes(filename):
filename = 'lower.md3'
bytes = ''
valuetoreturn = 1
try:
with open(filename,'rb') as fileptr:
if fileptr != None:
bytes = fileptr.read()
valuetoreturn = 333
except:
valuetoreturn = 991
return valuetoreturn
If the DLL runs this code via...
如果DLL通过...运行此代码
pValue = PyObject_CallObject(pFunc, arguments);
And gets a result via...
并通过...获得结果
iResult = PyInt_AsLong(pValue);
iResult has the value of 991 instead of 333 which would only happen if an exception had not occurred inside of 'with'. I know because I had the app calling the DLL pop up a message box with iResult in it.
iResult的值为991而不是333,只有在'with'内没有发生异常时才会发生。我知道因为我有应用程序调用DLL弹出一个带有iResult的消息框。
Even more interesting to me, this works...
对我来说更有意思,这个有用......
C:\Program Files (x86)\DeleD CE\Plugins>python
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import parseMD3
>>> testval = parseMD3.parsetest('junk')
>>> print testval
333
>>> exit()
So why does the CLI python return a different result that the same code being call from PyObject_CallObject? Why does 'with' behave differently here?
那么为什么CLI python会返回一个不同的结果,即从PyObject_CallObject调用相同的代码?为什么'with'在这里表现不同?
1 个解决方案
#1
with
does not handle exceptions. It only ensures that the file is closed when an exception occurs. If an exception occurs in the open()
expression itself, the with
block isn't even entered; fileptr
will never be bound to None
either.
与不处理异常。它只确保在发生异常时关闭文件。如果open()表达式本身发生异常,则甚至不输入with块; fileptr永远不会绑定到None。
You are catching all exceptions, including keyboard interrupts and memory errors, so we cannot begin to tell why the code fails when running under C++ control here.
您正在捕获所有异常,包括键盘中断和内存错误,因此我们无法在此处运行C ++控件时开始说明代码失败的原因。
Stick to a limited set of exceptions instead, like IOError
, and log the exception properly:
坚持使用一组有限的异常,比如IOError,并正确记录异常:
import logging
logger = logging.getLogger('__name__')
def getMD3Bytes(filename):
filename = 'lower.md3'
bytes = ''
valuetoreturn = 1
try:
with open(filename,'rb') as fileptr:
bytes = fileptr.read()
valuetoreturn = 333
except IOError:
logger.exception('Failed to open file properly')
valuetoreturn = 991
return valuetoreturn
The default config for the logger will output to stderr
, but you can configure it to log to a file instead:
记录器的默认配置将输出到stderr,但您可以将其配置为记录到文件:
logging.basicConfig(filename='/tmp/debug.log', level=logging.DEBUG)
#1
with
does not handle exceptions. It only ensures that the file is closed when an exception occurs. If an exception occurs in the open()
expression itself, the with
block isn't even entered; fileptr
will never be bound to None
either.
与不处理异常。它只确保在发生异常时关闭文件。如果open()表达式本身发生异常,则甚至不输入with块; fileptr永远不会绑定到None。
You are catching all exceptions, including keyboard interrupts and memory errors, so we cannot begin to tell why the code fails when running under C++ control here.
您正在捕获所有异常,包括键盘中断和内存错误,因此我们无法在此处运行C ++控件时开始说明代码失败的原因。
Stick to a limited set of exceptions instead, like IOError
, and log the exception properly:
坚持使用一组有限的异常,比如IOError,并正确记录异常:
import logging
logger = logging.getLogger('__name__')
def getMD3Bytes(filename):
filename = 'lower.md3'
bytes = ''
valuetoreturn = 1
try:
with open(filename,'rb') as fileptr:
bytes = fileptr.read()
valuetoreturn = 333
except IOError:
logger.exception('Failed to open file properly')
valuetoreturn = 991
return valuetoreturn
The default config for the logger will output to stderr
, but you can configure it to log to a file instead:
记录器的默认配置将输出到stderr,但您可以将其配置为记录到文件:
logging.basicConfig(filename='/tmp/debug.log', level=logging.DEBUG)