在unit eqmt Efectivo Demora Reserva Accidente Toneladas
Camion CAM336 9678 1498 2156 109 2342022
模块中,基础ctypes
类型执行C样式截断而不引发任何异常。例如,c_*
与c_uint8(0x120)
相同,与c_uint8(0x20)
相同。我希望创建继承c_uint8(32)
类型的类,如果类型超出其范围,将引发自定义异常。这是我到目前为止所提出的:
ctypes
虽然这可以按预期工作,但我很快意识到,对于每个from ctypes import *
class C_U8(c_uint8):
def __init__(self, value):
if value < 0 or value > 0xFF:
raise Exception("Nice try! Out of range")
类型来说,这将成为一个冗余的类。我想知道是否有更好的方法来执行此操作,例如创建一个从ctypes
模块继承所有类型的泛型类,并相应地检查每个类型?
答案 0 :(得分:3)
这是使用类工厂函数执行此操作的方法。您将函数传递给ctypes
数据类型类和所需的边界,并返回一个新类,该类在创建实例或更新其.value
属性时强制执行边界。
我只在Python 2.6.6上测试过这段代码,但它应该适用于Python 3(一旦修复了print
中的main()
语句)。
#!/usr/bin/env python
''' Bounded ctypes integer classes
Derive bounded versions of the ctypes integer datatype classes
For http://stackoverflow.com/q/31317553/4014959
Written by PM 2Ring 2015.07.10
'''
import ctypes
import sys
bounds_info = (
('c_byte', -2**7, 2**7-1),
('c_int', -2**31, 2**31-1),
('c_int16', -2**15, 2**15-1),
('c_int32', -2**31, 2**31-1),
('c_int64', -2**63, 2**63-1),
('c_int8', -2**7, 2**7-1),
('c_long', -2**31, 2**31-1),
('c_longlong', -2**63, 2**63-1),
('c_short', -2**15, 2**15-1),
('c_ubyte', 0, 2**8-1),
('c_uint', 0, 2**32-1),
('c_uint16', 0, 2**16-1),
('c_uint32', 0, 2**32-1),
('c_uint64', 0, 2**64-1),
('c_uint8', 0, 2**8-1),
('c_ulong', 0, 2**32-1),
('c_ulonglong', 0, 2**64-1),
('c_ushort', 0, 2**16-1),
)
def bounded_ctypes_class(name, lo, hi):
''' Derive a bounded version of a named ctypes integer class '''
parent = getattr(ctypes, name)
class Bint(parent):
def __init__(self, value=0):
if lo <= value <= hi:
super(Bint, self).__init__(value)
else:
raise ValueError, (
'Out of bounds: %s initial value %d is not between %d & %d'
% (self, value, lo, hi))
def __setattr__(self, attr, value):
#print "%s setattr('%s', %s) called" % (self, attr, value)
if attr == 'value' and not self._lolim <= value <= self._hilim:
raise ValueError, (
'Out of bounds: %s update value %d is not between %d & %d'
% (self, value, lo, hi))
super(Bint, self).__setattr__(attr, value)
newname = 'b' + name
Bint.__name__ = newname
Bint._lolim = lo
Bint._hilim = hi
return Bint
#Create the bounded classes
def create_classes():
module = sys.modules[__name__]
for name, lo, hi in bounds_info:
cls = bounded_ctypes_class(name, lo, hi)
setattr(module, cls.__name__, cls)
#Test the bounded classes
def main():
module = sys.modules[__name__]
for name, lo, hi in bounds_info:
newname = 'b' + name
cls = getattr(module, newname)
print 'Testing', cls
good = lo + 3 * (hi - lo) // 4
for v in (good, lo-1, hi+1):
try:
print 'Initializing with\n%d' % v
a = cls(v)
print a.value
a.value += 1
print a.value
a.value += hi
print a.value
except Exception as e:
print e
print
print 40 * '- ' + '\n'
#A test with "normal" instance creation syntax.
a = bc_byte(7); print a, a.value
a.value += 100; print a.value
try:
a.value += 30; print a.value
except Exception as e:
print e
create_classes()
if __name__ == '__main__':
main()
这是输出的最后一个屏幕:
Testing <class '__main__.bc_ulong'>
Initializing with
3221225471
3221225471
3221225472
Out of bounds: <bc_ulong object at 0xb732d3d4> update value 7516192767 is not between 0 & 4294967295
Initializing with
-1
Out of bounds: <bc_ulong object at 0xb732d38c> initial value -1 is not between 0 & 4294967295
Initializing with
4294967296
Out of bounds: <bc_ulong object at 0xb732d4ac> initial value 4294967296 is not between 0 & 4294967295
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Testing <class '__main__.bc_ulonglong'>
Initializing with
13835058055282163711
13835058055282163711
13835058055282163712
Out of bounds: <bc_ulonglong object at 0xb732d38c> update value 32281802128991715327 is not between 0 & 18446744073709551615
Initializing with
-1
Out of bounds: <bc_ulonglong object at 0xb732d4ac> initial value -1 is not between 0 & 18446744073709551615
Initializing with
18446744073709551616
Out of bounds: <bc_ulonglong object at 0xb732d3d4> initial value 18446744073709551616 is not between 0 & 18446744073709551615
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Testing <class '__main__.bc_ushort'>
Initializing with
49151
49151
49152
Out of bounds: <bc_ushort object at 0xb732d4ac> update value 114687 is not between 0 & 65535
Initializing with
-1
Out of bounds: <bc_ushort object at 0xb732d3d4> initial value -1 is not between 0 & 65535
Initializing with
65536
Out of bounds: <bc_ushort object at 0xb732d38c> initial value 65536 is not between 0 & 65535
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<bc_byte object at 0xb732d3d4> 7
107
Out of bounds: <bc_byte object at 0xb732d3d4> update value 137 is not between -128 & 127