System designTroubleshooting

NumPy module has no attribute float: fix the removed alias

Why NumPy 1.24 removed np.float and breaks the handeye calibrator, and the two fixes: pin NumPy 1.23.5 or replace the alias with the built-in float.

LumaSpec Vision10 min read Share on LinkedIn

On this page 8 sections
  1. 01Why does the handeye calibrator fail with module numpy has no attribute float?
  2. 02Which NumPy versions still accept np.float?
  3. 03How do I check which NumPy file Python is actually loading?
  4. 04Should I pin NumPy 1.23.5 or edit the baldor source?
  5. 05Why did pip's NumPy override the one apt installed?
  6. 06When should I rebuild on a clean controller instead of patching?
  7. 07How do I stop the numpy alias error from coming back?
  8. 08Questions

Your hand-eye calibration node dies before it opens a camera, with AttributeError: module 'numpy' has no attribute 'float'. The cause is a Python dependency conflict, not a hardware fault: NumPy 1.24 removed the deprecated np.float alias, and the baldor package that the ROS handeye calibrator imports still calls it at load time. This guide gives you the version numbers that decide the failure, the two fixes — pinning NumPy to 1.23.5 or replacing the alias with the built-in float — and the pip-versus-apt habit that let the wrong copy in. You finish with a stack that imports cleanly and a pin that keeps it that way.

Why does the handeye calibrator fail with module numpy has no attribute float?

The failure is an import-time conflict: NumPy 1.24 removed the deprecated np.float alias, and the baldor package that handeye.calibrator needs still calls it on its first import as _MAX_FLOAT = np.maximum_sctype(np.float).

Read the traceback from the bottom and the chain is plain. handeye/__init__.py imports HandEyeCalibrator and Setup from .calibrator; calibrator.py line 5 runs import baldor as br; and baldor/__init__.py line 13 executes the np.maximum_sctype(np.float) call. On NumPy 1.24 or newer that lookup fails inside NumPy's own __getattr__, the AttributeError propagates up, and the loader reports that it failed to load the Python module handeye.calibrator. Nothing has opened a camera or touched your frame grabbers: the process died at import, before any device call, so re-cabling the cell or changing camera settings cannot help.

Two neighbouring errors are not this one. An error starting with numpy.core.multiarray failed to import is a compiled binary mismatch between NumPy and an extension such as cv2, with a different fix — see numpy.core.multiarray failed to import: fix the cv2 version mismatch. And a solver that crashes mid-run, after imports succeed, is a different failure again, covered in hand-eye calibration solver crash.

Which NumPy versions still accept np.float?

Deprecated in NumPy 1.20 and removed in NumPy 1.24: releases from 1.20 to 1.23.x still run np.float with a DeprecationWarning, and 1.24.0 or newer raises the AttributeError you are seeing.

NumPy 1.20 introduced the warning; every 1.21, 1.22 and 1.23 release kept the alias working; 1.24 deleted it. The same release removed the whole alias family, each member a thin alias for a Python built-in: np.float to float, np.int to int, np.bool to bool, np.object to object, np.str to str, and np.long to int. Replacing alias with built-in leaves behaviour unchanged.

NumPy version np.float status What you see at import
Up to 1.19 Plain alias Works, no message
1.20 to 1.23.x Deprecated, still present DeprecationWarning, code runs
1.24 and newer Removed AttributeError: module 'numpy' has no attribute 'float'

One quirk matters if you plan to jump further forward: NumPy 2.0 reintroduced np.bool and np.long, but with different semantics, so an old script using them is not automatically correct again on 2.x. The np.float alias stays gone in every 2.x release.

How do I check which NumPy file Python is actually loading?

Ask the interpreter that runs the calibrator to print both the version and the file path; if the path lands in ~/.local/lib/python3.8/site-packages, a pip install is shadowing apt's system copy.

Run the three checks in the shell that launches the calibration node:

python3 -c "import numpy; print(numpy.__version__, numpy.__file__)"
pip show numpy
apt-cache policy python3-numpy

The first line prints the version that actually imports and where it came from; the second reports the pip-side install for your user; the third reports the apt-side system package. On the failing machine the traceback already gives the answer away: NumPy loaded from ~/.local/lib/python3.8/site-packages, the pip user-site folder, rather than from /usr/lib/python3/dist-packages, where apt puts python3-numpy. ROS Noetic runs on Python 3.8, so those two copies are the ones that can fight.

The pass condition for any fix is measurable: rerun the first command and get 1.23.5 from the version field, then import the package directly.

python3 -c "import baldor; print('baldor OK')"

A version that pip claims but the interpreter does not import usually means a second interpreter is in play — the same trap behind GenICam Python package not found.

Should I pin NumPy 1.23.5 or edit the baldor source?

Pin first, patch only if you cannot downgrade: numpy==1.23.5 repairs every removed alias across the whole stack in one install, while editing baldor fixes one file and leaves np.int or np.object elsewhere to crash the next import.

The pin is one command:

pip install --force-reinstall numpy==1.23.5

The --force-reinstall flag matters when pip believes a suitable NumPy is already installed or cached; it replaces the copy outright instead of trusting its records. Then rerun the two-line test from the previous section — that is the whole verification.

The patch, for a machine where some other tool genuinely requires NumPy 1.24 or newer: open /opt/ros/noetic/lib/python3/dist-packages/baldor/__init__.py and change line 13 from _MAX_FLOAT = np.maximum_sctype(np.float) to:

_MAX_FLOAT = np.float64

That is the same substitution the project's own fix applies — np.float64 instead of np.float — because the original expression resolved to a 64-bit float on standard builds anyway. For your own code, the simpler form works everywhere: replace np.float with the built-in float, np.int with int, and so on down the family from the table above.

The decision, stated plainly: if nothing in the environment needs NumPy 1.24 features, pin — it fixes every alias at once. If a dependency you cannot drop demands 1.24 or newer, patch every failing file in one pass. Dependency conflicts of this shape, where two packages disagree about a shared library, follow the same pattern as hand-eye calibration build errors, and the discipline of one pinned library version everywhere is the same one that settles a Docker build SDK version mismatch.

Why did pip's NumPy override the one apt installed?

Python searches your user site-packages before the system dist-packages directory, so one pip install that pulled numpy as a dependency hid apt's python3-numpy from every script that user runs.

pip and apt keep entirely separate records. apt installed python3-numpy into /usr/lib/python3/dist-packages and tracks it in its own database; pip knows nothing about it. So when some tool you installed needed a newer NumPy, pip built a second copy in ~/.local/lib/python3.8/site-packages, Python's module search found the user site first, and from that moment every script you run as that user imports pip's NumPy. The apt copy still exists; it is simply unreachable.

This is why the failure splits machines into two groups. Development boxes, where months of pip installs have accumulated, show the error; clean production images, which install only through apt, keep an older system NumPy and never do. pip check after any install session reports which declared requirements the current state breaks, and it is the cheapest early warning you can add. The ROS-side cousin of this problem, where the package is simply not where the interpreter looks, is covered in ROS camera package unavailable.

When should I rebuild on a clean controller instead of patching?

Move when the box serves several projects: if pip freeze shows a pile of hand-installed packages fighting over versions, one shared interpreter will keep breaking, and a dedicated controller with a clean image gives the calibration stack exactly one NumPy.

Rebuild in this order: clean OS image, ROS through apt, then only the pinned requirements.txt through pip. That reproduces the clean production machine — no inherited user-site packages, one NumPy, and the same import result on every boot. A hand-eye cell does not need much compute to run that way: 8 GB of memory carries Noetic plus the calibrator, and a controller with built-in light channels can drive the inspection strobes from the same box, so the cell runs one computer instead of two.

Controllers that fit that profile:

Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$2,419.00View partBuild a system with it

The MV-VC3301H-128G66 pairs an Intel Core i3 processor with 8 GB of memory and a 128 GB SSD, and its 5+ LAN ports leave headroom for the calibration cameras plus the robot network.

Vision controllersHikrobot MV-VC2140-128G40-1T VC2100 Vision Controller, N97, 8GB+128G SSD+ 1THDDMV-VC2140-128G40-1T
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$1,679.00View partBuild a system with it

The MV-VC2140-128G40-1T runs the same 8 GB of memory on an Intel N-series processor, adds a 1 TB HDD for captured calibration data sets, and keeps two USB 3 ports for dongles and commissioning tools alongside four built-in light channels.

Browse the full vision controllers range if the cell needs PoE camera ports or a different LAN count; the shop finder filters by both.

How do I stop the numpy alias error from coming back?

Write the pin down: a requirements file that states numpy==1.23.5, installed with pip install -r requirements.txt, turns today's manual downgrade into the enforced baseline for every future build of the cell.

The short list that keeps it fixed:

  • State the tested version explicitly in the stack's requirements.txt and install from it, not with ad-hoc installs.
  • Run pip check after every install session; it lists any package whose numpy requirement the current state no longer satisfies.
  • On boxes that do run NumPy 1.24 or newer, lint before shipping: the NPY001 rule in ruff flags every deprecated alias — np.float, np.int, np.bool, np.object, np.str, np.long — at review time, weeks before a traceback.
  • When a dependency forces the newer NumPy, patch the alias family across the whole tree in one pass instead of waiting for each file to fail on its own schedule.
  • Keep experiments in a virtual environment so the production interpreter inherits nothing from ~/.local.

Once imports are stable, the calibration itself is the next milestone. If your smart camera offers no built-in wizard, smart camera hand-eye calibration when no wizard exists picks robot poses that give the solver enough spread to converge. And if you would rather have the environment and the hardware sized together, send the parts list through the contact page and we will check the chain from controller to cable before you order.

Questions

Does this error mean a fault in my camera or frame grabber?

No. The AttributeError fires while Python imports the calibrator module, before any camera or device is opened, so cable termination, camera exposure settings and frame grabber configuration are uninvolved. Fix the Python environment and the hardware behaves exactly as before. A hardware problem shows up as a blank or corrupted image, not as an import traceback.

Can I install NumPy 2.x instead of downgrading to 1.23.5?

Not as the fix. np.float stays removed in NumPy 2.x; only np.bool and np.long came back, and with different semantics. Noetic-era packages also expect the 1.x API and compiled ABI, so 1.23.5 remains the tested ceiling for this stack. Move to 2.x only after patching every alias call and rebuilding the compiled dependencies against the new ABI.

Which other aliases disappeared together with np.float?

The whole deprecated alias family: np.float, np.int, np.bool, np.object, np.str and np.long, all deprecated in 1.20 and removed in 1.24. Each aliased a Python built-in — float, int, bool, object, str — so replacing alias with built-in keeps behaviour identical. Search the whole project at once: fixing one file usually exposes the next alias a week later.

Is downgrading to NumPy 1.23.5 risky for my other packages?

For a Noetic-era stack, rarely: 1.23.5 still offers the API those packages were written against. The real risk points the other way — a tool that requires NumPy 1.24 features. Run pip check straight after the downgrade: it lists every distribution whose declared numpy requirement is no longer satisfied, and you decide package by package whether to patch instead.

Why does pip not simply update the apt-installed python3-numpy?

They are separate package worlds. apt installs python3-numpy into the system dist-packages folder and records it in its own database; pip installs another copy into ~/.local and tells apt nothing. Both versions can coexist, and Python's module search order — user site first — decides which one imports. That silent coexistence, not a fault in either tool, is what breaks the stack.