Environment:
- OS: Linux (Raspberry Pi OS) — setup
ef-rp18
- Python version: 3.9
- Ethopy version: 0.0.8.8
- Database version:
Describe the bug
GPIO Lick/Proximity callbacks in RPPorts are armed in __init__, before Behavior.setup() runs and assigns beh.logger. A stray edge in that window triggers the callback while self.beh.logger is still None, raising AttributeError. RPi.GPIO swallows the exception, so the session continues but any real lick/proximity event in that window is silently lost.
To Reproduce
- Run an experiment on a Raspberry Pi setup using the
RPPorts interface
- During startup, between
_interface_setup() and beh.setup(self) in experiment.py:213-217, a kernel buffered GPIO edge fires the lick callback.
Expected behavior
GPIO callbacks should not be able to invoke Behavior.log_activity until Behavior.setup() has wired beh.logger. Either callback registration is deferred until after beh.setup(), or callbacks defensively guard against the unready state and log instead of crashing
Error message
2026-05-07 12:00:03 - datajoint - ERROR - Uncaught exception (logging.py:23)
Traceback (most recent call last):
File "/home/eflab/github/ethopy_package/src/ethopy/interfaces/RPPorts.py", line 273, in _lick_port_activated
self.beh.log_activity({**self.response.__dict__, 'time':self.resp_tmst})
File "/home/eflab/github/ethopy_package/src/ethopy/core/behavior.py", line 205, in log_activity
key = {**self.logger.trial_key,**activity.__dict__}
AttributeError: 'NoneType' object has no attribute 'trial_key'
Additional context
Experiment keeps running despite the error: RPi.GPIO callbacks run on a separate C-thread, an exception inside the callback is caught at the C/Python boundary and the thread loops back for the next edge. Datajoint's exception hook then downgrades the traceback to a log line, and Python doesn't propagate thread exceptions to the main thread. The state machine is oblivious, trials continue, and any lick/proximity events during the gap are silently dropped
Environment:
ef-rp18Describe the bug
GPIO Lick/Proximity callbacks in
RPPortsare armed in__init__, beforeBehavior.setup()runs and assignsbeh.logger. A stray edge in that window triggers the callback whileself.beh.loggeris stillNone, raisingAttributeError. RPi.GPIO swallows the exception, so the session continues but any real lick/proximity event in that window is silently lost.To Reproduce
RPPortsinterface_interface_setup()andbeh.setup(self)inexperiment.py:213-217, a kernel buffered GPIO edge fires the lick callback.Expected behavior
GPIO callbacks should not be able to invoke
Behavior.log_activityuntilBehavior.setup()has wiredbeh.logger. Either callback registration is deferred until afterbeh.setup(), or callbacks defensively guard against the unready state and log instead of crashingError message
Additional context
Experiment keeps running despite the error: RPi.GPIO callbacks run on a separate C-thread, an exception inside the callback is caught at the C/Python boundary and the thread loops back for the next edge. Datajoint's exception hook then downgrades the traceback to a log line, and Python doesn't propagate thread exceptions to the main thread. The state machine is oblivious, trials continue, and any lick/proximity events during the gap are silently dropped