Recording ACE stderr messages with ACEParser.interact()?

Pydelphin’s ace.response objects have an ERRORS field, however ACE’s stderr messages don’t seem to go in there when I call the ACEParser’s interact() method on a sentence which triggers the error.

Here, Mike says:

A profile processed with ACE and PyDelphin will not record the error as it is output on ACE’s stderr and it is not always feasible to match that to a input item during batch processing.

But what about sentence-by-sentence processing? Is there already an option to have the pydelphin’s ACE wrapper record the errors?

Just for a concrete example, here’s my call:

with ace.ACEParser(grammar,cmdargs=['-y','--yy-rules'],executable=ace_exec) as parser:
    for s in sentence_list:
        response = parser.interact(s)
        ace_responces.append(response)

Screenshot from 2022-08-25 12-57-47

Suppose ACE reports an error, ERROR: yy-mode input requested non-existant rule PR0CN00, and I just want to match this error to the input. I can probably do that myself (by capturing the stderr output I suppose?) but I wanted to check if there is already a way to call the interact() method which I am not finding in the docs.

PyDelphin used to capture stderr and fill in those NOTES, WARNINGS, and ERRORS fields, but that approach became untenable for longer-running processes because, as I recall, the limited buffer would fill with unconsumed messages and also these stderr strings would interject in the middle of an otherwise valid stdout line, so I switched to ignoring stderr and only using stdout. However, some of the code for capturing these things is still there, so you might try redirecting stderr to stdout:

parser = ace.ACEParser(..., stderr=subprocess.stdout)

No promises, though. Also, one issue is that PyDelphin should stop reading when it’s received a full response on stdout, so if the stderr messages appear after that, they would be lost or possibly grouped with the next item. We can’t just read until there’s no more lines because reading from the buffer is a blocking call, so the process would hang.

A better approach, perhaps, is to have a separate function to consume stderr, so you could do this:

response = parser.interact(...)
err = read_from_stderr()

That function could be asynchronous and/or have a timeout so it doesn’t block when it has exhausted the buffer.

1 Like