Integration · Analysis

Connect OPC UA to Python pandas / Jupyter

ProductPython pandas / Jupyter
CategoryAnalysis
OPC UA roleClient

Pulling OPC UA data straight into a DataFrame is the fastest way to answer a question about a machine, and the right tool for a one-off investigation. It is not a collector: a notebook that has to stay running is a production dependency nobody is monitoring.

Before you start

  • asyncua installed, and the synchronous wrapper if you dislike await in a notebook.
  • Read access to the server, and its certificate trusted if it requires security.
  • A clear question. Notebooks are excellent for answering one and poor at running forever.

Setting it up

  1. Use the synchronous wrapper in a notebookfrom asyncua.sync import Client gives you the same API without asyncio, which behaves far better inside Jupyter's own event loop than trying to nest one.
  2. Collect into a list, then build the DataFrame onceAppending to a DataFrame per notification is slow and allocates constantly. Buffer notifications in a list of dicts and construct the DataFrame at the end.
  3. Keep the status code and both timestamps as columnsYou will need them. An analysis that silently averages an UncertainLastUsableValue produces a number nobody can defend, and you cannot reconstruct the status after discarding it.
  4. Index on SourceTimestamp, in UTCSet it as a timezone-aware DatetimeIndex. Mixing naive local timestamps from several machines is how a shift boundary ends up an hour wrong.
  5. Pull history rather than waitingIf the server supports historical access, read a past window instead of sitting in a subscription for an hour. If you need shift aggregates, ask the server for TimeAverage or PercentGood - it computes them far more cheaply than you can.
  6. Promote to a real collector when it worksOnce the notebook answers the question repeatedly, move the logic into a small service with reconnection and monitoring. A notebook left running on someone's laptop is a production incident waiting for a lid to close.

What the address space looks like

Whatever you select, flattened into columns. Structured values decode into Python objects if you load the server's data type definitions first, which you can then normalise into columns. Companion-spec structure is available if you browse for it, but pandas will not preserve it for you.

The traps

  • Jupyter runs its own event loop, so the plain async client can behave oddly inside a cell. The synchronous wrapper avoids the problem entirely.
  • A subscription in a notebook stops when the kernel restarts, silently. Any dataset collected that way has gaps you will not notice until you plot it.
  • Resampling before checking status codes is the classic analysis error: bad and uncertain values get averaged into a clean-looking series.
  • Timezone-naive timestamps from multiple servers cannot be compared safely. Normalise to UTC on ingestion, not at plot time.
  • Long unbounded history reads against a production historian will get you a phone call. Bound every request.

Getting OEE data out of it

Ideal for prototyping an OEE calculation before committing it to a platform, and for the argument about definitions that always follows. Compute availability from state durations, performance against a stated ideal cycle time, quality from reject counts, and keep every assumption in a cell next to the number. It is a modelling tool, not a monitoring one - the moment the answer needs to exist every shift, it belongs in a service.

Verify before you rely on this: Library APIs move between major versions. Pin asyncua and pandas in the notebook and record the versions alongside any result you intend to act on.
Related integrations

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Machine Data → OEE Mapping Kit
Which nodes to subscribe to, how they become Availability, Performance and Quality, and which companion specification already gives you the answer, so you stop inventing tags.
Get the free mapping kit →
Free, no course, no login