mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#4576 Python: Improve error handling and add example
This commit is contained in:
parent
84495641f9
commit
197279ccbf
@ -173,6 +173,7 @@ if (RESINSIGHT_GRPC_PYTHON_EXECUTABLE)
|
|||||||
"rips/examples/CommandExample.py"
|
"rips/examples/CommandExample.py"
|
||||||
"rips/examples/CaseGridGroup.py"
|
"rips/examples/CaseGridGroup.py"
|
||||||
"rips/examples/CaseInfoStreamingExample.py"
|
"rips/examples/CaseInfoStreamingExample.py"
|
||||||
|
"rips/examples/ErrorHandling.py"
|
||||||
"rips/examples/SoilPorvAsync.py"
|
"rips/examples/SoilPorvAsync.py"
|
||||||
"rips/examples/SoilPorvSync.py"
|
"rips/examples/SoilPorvSync.py"
|
||||||
"rips/examples/SelectedCases.py"
|
"rips/examples/SelectedCases.py"
|
||||||
|
@ -8,5 +8,5 @@ message Empty
|
|||||||
|
|
||||||
message ClientToServerStreamReply
|
message ClientToServerStreamReply
|
||||||
{
|
{
|
||||||
int64 values_accepted = 1;
|
int64 accepted_value_count = 1;
|
||||||
}
|
}
|
@ -25,13 +25,7 @@ class Commands:
|
|||||||
self.commands = CmdRpc.CommandsStub(channel)
|
self.commands = CmdRpc.CommandsStub(channel)
|
||||||
|
|
||||||
def __execute(self, **commandParams):
|
def __execute(self, **commandParams):
|
||||||
try:
|
|
||||||
return self.commands.Execute(Cmd.CommandParams(**commandParams))
|
return self.commands.Execute(Cmd.CommandParams(**commandParams))
|
||||||
except grpc.RpcError as e:
|
|
||||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
|
||||||
print("Command not found", commandParams.keys())
|
|
||||||
else:
|
|
||||||
print("Other error", e)
|
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# Case Control Commands
|
# Case Control Commands
|
||||||
@ -71,8 +65,6 @@ class Commands:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path))
|
commandReply = self.__execute(loadCase=Cmd.FilePathRequest(path=path))
|
||||||
assert(commandReply is not None)
|
|
||||||
assert(commandReply.HasField("loadCaseResult"))
|
|
||||||
return Case(self.channel, commandReply.loadCaseResult.id)
|
return Case(self.channel, commandReply.loadCaseResult.id)
|
||||||
|
|
||||||
def replaceCase(self, newGridFile, caseId=0):
|
def replaceCase(self, newGridFile, caseId=0):
|
||||||
@ -107,14 +99,10 @@ class Commands:
|
|||||||
A case group id and name
|
A case group id and name
|
||||||
"""
|
"""
|
||||||
commandReply = self.__execute(createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(casePaths=casePaths))
|
commandReply = self.__execute(createGridCaseGroup=Cmd.CreateGridCaseGroupRequest(casePaths=casePaths))
|
||||||
assert(commandReply is not None)
|
|
||||||
assert(commandReply.HasField("createGridCaseGroupResult"))
|
|
||||||
return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName)
|
return (commandReply.createGridCaseGroupResult.groupId, commandReply.createGridCaseGroupResult.groupName)
|
||||||
|
|
||||||
def createStatisticsCase(self, caseGroupId):
|
def createStatisticsCase(self, caseGroupId):
|
||||||
commandReply = self.__execute(createStatisticsCase=Cmd.CreateStatisticsCaseRequest(caseGroupId=caseGroupId))
|
commandReply = self.__execute(createStatisticsCase=Cmd.CreateStatisticsCaseRequest(caseGroupId=caseGroupId))
|
||||||
assert(commandReply is not None)
|
|
||||||
assert(commandReply.HasField("createStatisticsCaseResult"))
|
|
||||||
return commandReply.createStatisticsCaseResult.caseId;
|
return commandReply.createStatisticsCaseResult.caseId;
|
||||||
|
|
||||||
##################
|
##################
|
||||||
|
@ -12,6 +12,13 @@ from Definitions_pb2 import ClientToServerStreamReply
|
|||||||
|
|
||||||
class Properties:
|
class Properties:
|
||||||
""" Class for streaming properties to and from ResInsight
|
""" Class for streaming properties to and from ResInsight
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
chunkSize(int): The size of each chunk during value streaming.
|
||||||
|
A good chunk size is 64KiB = 65536B.
|
||||||
|
Meaning the ideal number of doubles would be 8192.
|
||||||
|
However we need overhead space, so the default is 8160.
|
||||||
|
This leaves 256B for overhead.
|
||||||
"""
|
"""
|
||||||
def __init__(self, case):
|
def __init__(self, case):
|
||||||
"""
|
"""
|
||||||
@ -20,6 +27,8 @@ class Properties:
|
|||||||
"""
|
"""
|
||||||
self.case = case
|
self.case = case
|
||||||
self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel)
|
self.propertiesStub = Properties_pb2_grpc.PropertiesStub(self.case.channel)
|
||||||
|
self.chunkSize = 8160
|
||||||
|
|
||||||
|
|
||||||
def __generatePropertyInputIterator(self, values_iterator, parameters):
|
def __generatePropertyInputIterator(self, values_iterator, parameters):
|
||||||
chunk = Properties_pb2.PropertyInputChunk()
|
chunk = Properties_pb2.PropertyInputChunk()
|
||||||
@ -32,11 +41,7 @@ class Properties:
|
|||||||
yield chunk
|
yield chunk
|
||||||
|
|
||||||
def __generatePropertyInputChunks(self, array, parameters):
|
def __generatePropertyInputChunks(self, array, parameters):
|
||||||
# Each double is 8 bytes. A good chunk size is 64KiB = 65536B
|
|
||||||
# Meaning ideal number of doubles would be 8192.
|
|
||||||
# However we need overhead space, so if we choose 8160 in chunk size
|
|
||||||
# We have 256B left for overhead which should be plenty
|
|
||||||
chunkSize = 44431
|
|
||||||
index = -1
|
index = -1
|
||||||
while index < len(array):
|
while index < len(array):
|
||||||
chunk = Properties_pb2.PropertyInputChunk()
|
chunk = Properties_pb2.PropertyInputChunk()
|
||||||
@ -44,7 +49,7 @@ class Properties:
|
|||||||
chunk.params.CopyFrom(parameters)
|
chunk.params.CopyFrom(parameters)
|
||||||
index += 1
|
index += 1
|
||||||
else:
|
else:
|
||||||
actualChunkSize = min(len(array) - index + 1, chunkSize)
|
actualChunkSize = min(len(array) - index + 1, self.chunkSize)
|
||||||
chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actualChunkSize]))
|
chunk.values.CopyFrom(Properties_pb2.PropertyChunk(values = array[index:index+actualChunkSize]))
|
||||||
index += actualChunkSize
|
index += actualChunkSize
|
||||||
|
|
||||||
@ -184,14 +189,9 @@ class Properties:
|
|||||||
property_name = propertyName,
|
property_name = propertyName,
|
||||||
time_step = timeStep,
|
time_step = timeStep,
|
||||||
porosity_model = porosityModelEnum)
|
porosity_model = porosityModelEnum)
|
||||||
try:
|
|
||||||
request_iterator = self.__generatePropertyInputIterator(values_iterator, request)
|
request_iterator = self.__generatePropertyInputIterator(values_iterator, request)
|
||||||
self.propertiesStub.SetActiveCellProperty(request_iterator)
|
self.propertiesStub.SetActiveCellProperty(request_iterator)
|
||||||
except grpc.RpcError as e:
|
|
||||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
|
||||||
print("Command not found")
|
|
||||||
else:
|
|
||||||
print("Other error", e)
|
|
||||||
|
|
||||||
def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'):
|
def setActiveCellProperty(self, values, propertyType, propertyName, timeStep, porosityModel = 'MATRIX_MODEL'):
|
||||||
"""Set a cell property for all active cells.
|
"""Set a cell property for all active cells.
|
||||||
@ -210,17 +210,10 @@ class Properties:
|
|||||||
property_name = propertyName,
|
property_name = propertyName,
|
||||||
time_step = timeStep,
|
time_step = timeStep,
|
||||||
porosity_model = porosityModelEnum)
|
porosity_model = porosityModelEnum)
|
||||||
try:
|
|
||||||
request_iterator = self.__generatePropertyInputChunks(values, request)
|
request_iterator = self.__generatePropertyInputChunks(values, request)
|
||||||
reply = self.propertiesStub.SetActiveCellProperty(request_iterator)
|
reply = self.propertiesStub.SetActiveCellProperty(request_iterator)
|
||||||
if reply.values_accepted != len(values):
|
if reply.accepted_value_count < len(values):
|
||||||
print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage");
|
raise IndexError
|
||||||
|
|
||||||
except grpc.RpcError as e:
|
|
||||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
|
||||||
print("Command not found")
|
|
||||||
else:
|
|
||||||
print("Other error", e)
|
|
||||||
|
|
||||||
def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'):
|
def setGridProperty(self, values, propertyType, propertyName, timeStep, gridIndex = 0, porosityModel = 'MATRIX_MODEL'):
|
||||||
"""Set a cell property for all grid cells.
|
"""Set a cell property for all grid cells.
|
||||||
@ -241,14 +234,8 @@ class Properties:
|
|||||||
time_step = timeStep,
|
time_step = timeStep,
|
||||||
grid_index = gridIndex,
|
grid_index = gridIndex,
|
||||||
porosity_model = porosityModelEnum)
|
porosity_model = porosityModelEnum)
|
||||||
try:
|
|
||||||
request_iterator = self.__generatePropertyInputChunks(values, request)
|
request_iterator = self.__generatePropertyInputChunks(values, request)
|
||||||
reply = self.propertiesStub.SetGridProperty(request_iterator)
|
reply = self.propertiesStub.SetGridProperty(request_iterator)
|
||||||
if reply.values_accepted != len(values):
|
if reply.accepted_value_count < len(values):
|
||||||
print("ERROR: Attempted to write outside bounds of " + propertyName + " data storage");
|
raise IndexError
|
||||||
|
|
||||||
except grpc.RpcError as e:
|
|
||||||
if e.code() == grpc.StatusCode.NOT_FOUND:
|
|
||||||
print("Command not found")
|
|
||||||
else:
|
|
||||||
print("Other error", e)
|
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
import rips
|
||||||
|
import grpc
|
||||||
|
|
||||||
|
resInsight = rips.Instance.find()
|
||||||
|
|
||||||
|
case = None
|
||||||
|
|
||||||
|
# Try loading a non-existing case. We should get a grpc.RpcError exception from the server
|
||||||
|
try:
|
||||||
|
case = resInsight.project.loadCase("Nonsense")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
print("Expected Server Exception Received: ", e)
|
||||||
|
|
||||||
|
case = resInsight.project.case(id=0)
|
||||||
|
if case is not None:
|
||||||
|
results = case.properties.activeCellProperty('STATIC_NATIVE', 'PORO', 0)
|
||||||
|
activeCellCount = len(results)
|
||||||
|
|
||||||
|
# Send the results back to ResInsight inside try / except construct
|
||||||
|
try:
|
||||||
|
case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||||
|
print("Everything went well as expected")
|
||||||
|
except: # Match any exception, but it should not happen
|
||||||
|
print("Ooops!")
|
||||||
|
|
||||||
|
# Add another value, so this is outside the bounds of the active cell result storage
|
||||||
|
results.append(1.0)
|
||||||
|
|
||||||
|
# This time we should get a grpc.RpcError exception, which is a server side error.
|
||||||
|
try:
|
||||||
|
case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||||
|
print("Everything went well??")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
print("Expected Server Exception Received: ", e)
|
||||||
|
except IndexError:
|
||||||
|
print ("Got index out of bounds error. This shouldn't happen here")
|
||||||
|
|
||||||
|
# With a chunk size exactly matching the active cell count the server will not
|
||||||
|
# be able to see any error as it will successfully close the stream after receiving
|
||||||
|
# the correct number of values, even if the python client has more chunks to send
|
||||||
|
case.properties.chunkSize = activeCellCount
|
||||||
|
|
||||||
|
try:
|
||||||
|
case.properties.setActiveCellProperty(results, 'GENERATED', 'POROAPPENDED', 0)
|
||||||
|
print("Everything went well??")
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
print("Got unexpected server exception", e, "This should not happen now")
|
||||||
|
except IndexError:
|
||||||
|
print ("Got expected index out of bounds error on client side")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
import rips
|
import rips
|
||||||
import time
|
import time
|
||||||
|
import grpc
|
||||||
|
|
||||||
resInsight = rips.Instance.find()
|
resInsight = rips.Instance.find()
|
||||||
start = time.time()
|
start = time.time()
|
||||||
@ -12,7 +13,11 @@ results = []
|
|||||||
for (poro, permx) in zip(poroResults, permxResults):
|
for (poro, permx) in zip(poroResults, permxResults):
|
||||||
results.append(poro * permx)
|
results.append(poro * permx)
|
||||||
|
|
||||||
|
try:
|
||||||
case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0)
|
case.properties.setActiveCellProperty(results, 'GENERATED', 'POROPERMXSY', 0)
|
||||||
|
except grpc.RpcError as e:
|
||||||
|
print("Exception Received: ", e)
|
||||||
|
|
||||||
|
|
||||||
end = time.time()
|
end = time.time()
|
||||||
print("Time elapsed: ", end - start)
|
print("Time elapsed: ", end - start)
|
||||||
|
@ -341,8 +341,8 @@ void RiaGrpcClientToServerStreamCallback<ServiceT, RequestT, ReplyT, StateHandle
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CAF_ASSERT(m_stateHandler->nrOfValuesReceived() <= m_stateHandler->cellCount());
|
CAF_ASSERT(m_stateHandler->streamedValueCount() <= m_stateHandler->cellCount());
|
||||||
if (m_stateHandler->nrOfValuesReceived() == m_stateHandler->cellCount())
|
if (m_stateHandler->streamedValueCount() == m_stateHandler->cellCount())
|
||||||
{
|
{
|
||||||
this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST);
|
this->setNextCallState(RiaGrpcCallbackInterface::FINISH_REQUEST);
|
||||||
m_reader.Finish(this->m_reply, grpc::Status::OK, this);
|
m_reader.Finish(this->m_reply, grpc::Status::OK, this);
|
||||||
|
@ -56,7 +56,7 @@ public:
|
|||||||
RiaCellResultsStateHandler(bool clientStreamer = false)
|
RiaCellResultsStateHandler(bool clientStreamer = false)
|
||||||
: m_request(nullptr)
|
: m_request(nullptr)
|
||||||
, m_eclipseCase(nullptr)
|
, m_eclipseCase(nullptr)
|
||||||
, m_nrOfValuesReceived(0u)
|
, m_streamedValueCount(0u)
|
||||||
, m_cellCount(0u)
|
, m_cellCount(0u)
|
||||||
, m_clientStreamer(clientStreamer)
|
, m_clientStreamer(clientStreamer)
|
||||||
{
|
{
|
||||||
@ -73,9 +73,9 @@ public:
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
size_t nrOfValuesReceived() const
|
size_t streamedValueCount() const
|
||||||
{
|
{
|
||||||
return m_nrOfValuesReceived;
|
return m_streamedValueCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -150,9 +150,9 @@ public:
|
|||||||
const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::PropertyChunk));
|
const size_t packageSize = RiaGrpcServiceInterface::numberOfMessagesForByteCount(sizeof(rips::PropertyChunk));
|
||||||
size_t packageIndex = 0u;
|
size_t packageIndex = 0u;
|
||||||
reply->mutable_values()->Reserve((int)packageSize);
|
reply->mutable_values()->Reserve((int)packageSize);
|
||||||
for (; packageIndex < packageSize && m_nrOfValuesReceived < m_cellCount; ++packageIndex, ++m_nrOfValuesReceived)
|
for (; packageIndex < packageSize && m_streamedValueCount < m_cellCount; ++packageIndex, ++m_streamedValueCount)
|
||||||
{
|
{
|
||||||
reply->add_values(cellResult(m_nrOfValuesReceived));
|
reply->add_values(cellResult(m_streamedValueCount));
|
||||||
}
|
}
|
||||||
if (packageIndex > 0u)
|
if (packageIndex > 0u)
|
||||||
{
|
{
|
||||||
@ -167,25 +167,24 @@ public:
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
Status receiveStreamRequest(const PropertyInputChunk* request, ClientToServerStreamReply* reply)
|
Status receiveStreamRequest(const PropertyInputChunk* request, ClientToServerStreamReply* reply)
|
||||||
{
|
{
|
||||||
CAF_ASSERT(!request->has_params());
|
|
||||||
if (request->has_values())
|
if (request->has_values())
|
||||||
{
|
{
|
||||||
auto values = request->values().values();
|
auto values = request->values().values();
|
||||||
if (!values.empty())
|
if (!values.empty())
|
||||||
{
|
{
|
||||||
size_t currentCellIdx = m_nrOfValuesReceived;
|
size_t currentCellIdx = m_streamedValueCount;
|
||||||
m_nrOfValuesReceived += values.size();
|
m_streamedValueCount += values.size();
|
||||||
|
|
||||||
for (int i = 0; i < values.size() && currentCellIdx < m_cellCount; ++i, ++currentCellIdx)
|
for (int i = 0; i < values.size() && currentCellIdx < m_cellCount; ++i, ++currentCellIdx)
|
||||||
{
|
{
|
||||||
setCellResult(currentCellIdx, values[i]);
|
setCellResult(currentCellIdx, values[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nrOfValuesReceived > m_cellCount)
|
if (m_streamedValueCount > m_cellCount)
|
||||||
{
|
{
|
||||||
return grpc::Status(grpc::OUT_OF_RANGE, "Attempting to write out of bounds");
|
return grpc::Status(grpc::OUT_OF_RANGE, "Attempting to write out of bounds");
|
||||||
}
|
}
|
||||||
reply->set_values_accepted(static_cast<int64_t>(currentCellIdx));
|
reply->set_accepted_value_count(static_cast<int64_t>(currentCellIdx));
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +223,7 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
const rips::PropertyRequest* m_request;
|
const rips::PropertyRequest* m_request;
|
||||||
RimEclipseCase* m_eclipseCase;
|
RimEclipseCase* m_eclipseCase;
|
||||||
size_t m_nrOfValuesReceived;
|
size_t m_streamedValueCount;
|
||||||
size_t m_cellCount;
|
size_t m_cellCount;
|
||||||
bool m_clientStreamer;
|
bool m_clientStreamer;
|
||||||
RigEclipseResultAddress m_resultAddress;
|
RigEclipseResultAddress m_resultAddress;
|
||||||
|
Loading…
Reference in New Issue
Block a user