pythonnidaqmx

nidaqmx: prevent task from closing after being altered in function


I am trying to write an API that takes advantage of the python wrapper for NI-DAQmx, and need to have a global list of tasks that can be edited across the module.

Here is what I have tried so far:

1) Created an importable dictionary of tasks which is updated whenever a call is made to ni-daqmx. The function endpoint processes data from an HTTPS request, I promise it's not just a pointless wrapper around the ni-daqmx library itself.

e.g., on startup, the following is created:

#./daq/__init.py__
import nidaqmx
# ... other stuff ...#
TASKS = {}

then, the user can create a task by calling this endpoint

#./daq/task/task.py
from daq import TASKS

# ... 

def api_create_task_endpoint(task_id):
    try:
        task = nidaqmx.Task(new_task_name=task_id)
        TASKS[task_id] = task
    except Exception:
        # handle it

Everything up to here works as it should. I can get the task list, and the task stays open. I also tried explicitly calling task.control(nidaqmx.constants.TaskMode.TASK_RESERVE), but the following code gives me the same issue no matter what.

When I try to add channels to the task, it closes at the end of the function call no matter how I set the state.

#./daq/task/channels.py
from daq import TASKS

def api_add_channel_task_endpoint(task_id, channel_type, function):
    # channel_type corresponds to ni-daqmx channel modules (e.g. ai_channels).
    # function corresponds to callable functions (e.g. add_ai_voltage_chan)
    # do some preliminary checks (e.g. task exists, channel type valid)
    channels = get_chans_from_json_post()
    with TASKS[task_id] as task:
        getattr(getattr(task, channel_type), function)(channels)
        # e.g. task.ai_channels.add_ai_voltage_chan("Dev1/ai0")

This is apparently closing the task. When I call api_create_task_endpoint(task_id) again, I receive the DaqResourceWarning that the task has been closed, and no longer exists.

I similarly tried setting the TaskMode using task.control here, to no avail.

I would like to be able to make edits to the task by storing it in the module-wide TASKS dict, but cannot keep the Task open long enough to do so.

2) I also tried implementing this using the NI-MAX save feature. The issue with this is that tasks cannot be saved unless they already contain channels, which I don't necessarily want to do immediately after creating the task.

I attempted to work around this by adding to the api_create_task_endpoint() some default behavior which just adds a random channel that is removed on the first channel added by the user. Problem is, I can't find any documentation for a way to remove channels from a task after adding them without a GUI (this is running on CENTOS, so GUI is a non-starter).

Thank you so much for any help!


Solution

  • I haven't use the Python bindings for NI-DAQmx, but

    with TASKS[task_id] as task:

    looks like it would stop and clear the task immediately after updating it because the program flow leaves the with block and Task.__exit__() executes.

    Because you expect these tasks to live while the Python module is in use, my recommendation is to only use task.control() when you need to change a task's state.