Python:相同的字符串切片,两种不同的结果
Python: Identical string slicing, two different results
在某个地方我是个白痴,但我找不到。
我是运行一个通过ODBC使用PostgreSQL数据库的Python脚本。我正在尝试从数据库异常消息中提取有意义的部分。这是原始消息,为便于阅读添加了换行符:
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None)
请注意,此字符串中有两组括号。首先,我找到外面的位置并将它们切掉。这给出了预期的结果:
-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None
然后,使用尽可能相同的代码,我去掉了另一组括号和它们之外的所有内容。这给出了这个结果:
(0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -214746725
左括号仍然在这里,即使我以相同的方式使用 find() 方法的结果,两次都在左括号位置添加一个作为切片的开始。
代码如下:
print (errorString)
openParenLocation = errorString.find('(')
closeParenLocation = errorString.rfind(')')
strippedString = errorString[openParenLocation + 1:closeParenLocation]
openParenLocation = strippedString.find('(')
closeParenLocation = strippedString.rfind(')')
dbErrorString = errorString[openParenLocation + 1:closeParenLocation]
print (strippedString)
print ("{}, {}".format(openParenLocation, closeParenLocation))
print (dbErrorString)
这是原始输出,没有添加换行符:
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -2147467259), None)
-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -2147467259), None
36, 191
(0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -214746725
使用更小的字符串的测试代码按预期工作:
testString = "(abc(def)ghij)"
openParenLocation = testString.find('(')
closeParenLocation = testString.rfind(')')
strippedTestString = testString[openParenLocation + 1:closeParenLocation]
openParenLocation = strippedTestString.find('(')
closeParenLocation = strippedTestString.rfind(')')
finalTestString = strippedTestString[openParenLocation + 1:closeParenLocation]
非常感谢。
看起来像这样一行:
dbErrorString = errorString[openParenLocation + 1:closeParenLocation]
应该改为:
dbErrorString = strippedString[openParenLocation + 1:closeParenLocation]
鉴于您的字符串看起来像 Python 语法,您是否考虑过使用标准 ast
库模块来为您完成所有这些工作?
>>> errorString =r"""\
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None)"""
>>> import ast
>>> a = ast.parse(errorString).body[0].value
>>> a
<_ast.Tuple at 0x10802d3d0>
>>> a.elts[0]
<_ast.Num at 0x10802d410>
>>> a.elts[0].n
-2147352567
>>> a.elts[1]
<_ast.Str at 0x10802d450>
>>> a.elts[1].s
'Exception occurred.'
>>> a.elts[2]
<_ast.Tuple at 0x10802d490>
>>> # so now lather/rinse repeat: iterate over a.elts[2].elts
>>> a.elts[3]
<_ast.Name at 0x10802d650>
>>> a.elts[3].id
'None'
一种更简单的方法是使用ast.literal_eval
将字符串直接转换为它所描述的Python 对象。它类似于内置 eval
,但从安全角度来看是安全的,因为它不会评估任何非文字内容(因此,任何恶意 errorString
内容都不会被执行)。
>>> a = ast.literal_eval(errorString)
>>> a[0]
-2147352567
>>> a[1]
'Exception occurred.'
>>> a[2][0]
0
等等
在某个地方我是个白痴,但我找不到。
我是运行一个通过ODBC使用PostgreSQL数据库的Python脚本。我正在尝试从数据库异常消息中提取有意义的部分。这是原始消息,为便于阅读添加了换行符:
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None)
请注意,此字符串中有两组括号。首先,我找到外面的位置并将它们切掉。这给出了预期的结果:
-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None
然后,使用尽可能相同的代码,我去掉了另一组括号和它们之外的所有内容。这给出了这个结果:
(0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -214746725
左括号仍然在这里,即使我以相同的方式使用 find() 方法的结果,两次都在左括号位置添加一个作为切片的开始。
代码如下:
print (errorString)
openParenLocation = errorString.find('(')
closeParenLocation = errorString.rfind(')')
strippedString = errorString[openParenLocation + 1:closeParenLocation]
openParenLocation = strippedString.find('(')
closeParenLocation = strippedString.rfind(')')
dbErrorString = errorString[openParenLocation + 1:closeParenLocation]
print (strippedString)
print ("{}, {}".format(openParenLocation, closeParenLocation))
print (dbErrorString)
这是原始输出,没有添加换行符:
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -2147467259), None)
-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -2147467259), None
36, 191
(0, 'Microsoft OLE DB Provider for ODBC Drivers', 'ERROR: Charge not in a correct status to delete;\nError while executing the query', None, 0, -214746725
使用更小的字符串的测试代码按预期工作:
testString = "(abc(def)ghij)"
openParenLocation = testString.find('(')
closeParenLocation = testString.rfind(')')
strippedTestString = testString[openParenLocation + 1:closeParenLocation]
openParenLocation = strippedTestString.find('(')
closeParenLocation = strippedTestString.rfind(')')
finalTestString = strippedTestString[openParenLocation + 1:closeParenLocation]
非常感谢。
看起来像这样一行:
dbErrorString = errorString[openParenLocation + 1:closeParenLocation]
应该改为:
dbErrorString = strippedString[openParenLocation + 1:closeParenLocation]
鉴于您的字符串看起来像 Python 语法,您是否考虑过使用标准 ast
库模块来为您完成所有这些工作?
>>> errorString =r"""\
(-2147352567, 'Exception occurred.', (0, 'Microsoft OLE DB Provider for ODBC Drivers',
'ERROR: Charge not in a correct status to delete;\nError while executing the query',
None, 0, -2147467259), None)"""
>>> import ast
>>> a = ast.parse(errorString).body[0].value
>>> a
<_ast.Tuple at 0x10802d3d0>
>>> a.elts[0]
<_ast.Num at 0x10802d410>
>>> a.elts[0].n
-2147352567
>>> a.elts[1]
<_ast.Str at 0x10802d450>
>>> a.elts[1].s
'Exception occurred.'
>>> a.elts[2]
<_ast.Tuple at 0x10802d490>
>>> # so now lather/rinse repeat: iterate over a.elts[2].elts
>>> a.elts[3]
<_ast.Name at 0x10802d650>
>>> a.elts[3].id
'None'
一种更简单的方法是使用ast.literal_eval
将字符串直接转换为它所描述的Python 对象。它类似于内置 eval
,但从安全角度来看是安全的,因为它不会评估任何非文字内容(因此,任何恶意 errorString
内容都不会被执行)。
>>> a = ast.literal_eval(errorString)
>>> a[0]
-2147352567
>>> a[1]
'Exception occurred.'
>>> a[2][0]
0
等等