Sep 5, 2026 · python · robotics · programming-languages · choosing-tools
Can You Build a Real Robot in Python Only?
Yes for most robots. The limit is not Python speed but whether one part of the machine must hold a beat nothing may interrupt, and hardware can hold it.
Yes, you can build a real robot in Python alone, and dropping to C++ or Rust is needed less often than the internet claims. The deciding question is not the language but whether some part of the machine must hold a beat nobody may interrupt. That part usually lives in firmware or in a small compiled loop beside your Python, joined by middleware such as ROS 2 or HORUS. The rest of this post is for Python-first developers deciding whether to commit to one language or start learning a second.
The script works. The arm picks the block up, the camera sees it, and it did the whole thing eleven times in a row while you filmed it.
Then you add the second camera and the motion goes rough. Not slow, rough, as though the arm is being shoved along rather than driven. You add a thread and it gets worse in a new way. You read that Python has a lock which stops two threads running at once, and you cannot tell whether that is your problem or just a thing people say. Every so often the arm pauses for a reason you cannot find anywhere in your own code.
Somebody on a forum tells you to rewrite it in C++. Somebody else says they run a warehouse machine in Python and have never had a problem. Both sound confident. You cannot tell which one is describing a robot like yours, and you would rather not spend three months learning a language only to discover the answer was a thread you should never have started.
Can a robot really run on Python alone?
Yes, a real robot can run on Python alone, and plenty of machines doing useful work every day contain no line of code their builders wrote in anything else. The question is usually asked as though it were about raw language speed, and it almost never is. What actually decides it is whether some part of your machine has to act on a beat that nothing is allowed to interrupt. A wheeled base that crosses a corridor, an arm that picks at roughly human pace, an inspection rover that stops and takes a picture, a camera-driven sorter: all of these are comfortable in Python from the top of the stack to the bottom of the code you wrote. The machines where Python alone comes apart are the ones that fall over when a command is late, press a tool against a surface, or drive motors directly with no controller in between. The trap is not that Python is slow. The trap is that a Python program can pause when it chooses, and a motor does not care why.
What does Python only actually mean once you look underneath?
Python only means that you write only Python, and it has never meant that only Python runs. Your array library is compiled. The camera driver is C with a friendly wrapper. The motor controller on the robot runs firmware nobody on your team wrote and nobody wants to. The scheduler deciding when your program gets the processor is part of the operating system. Compiled code is already doing the heavy lifting in every Python robot that works, which means the honest question is not whether compiled code is involved but whether you must write and maintain any of it. That reframing puts most language arguments back where they belong. When an experienced person says the fast part has to be in C++, what they usually mean is that the fast part has to live somewhere your Python pauses cannot reach: a separate process, a microcontroller, a vendor's controller board. Choosing where the beat lives is the real decision, and the language follows from it rather than the other way around.
What are your actual options if you want to stay in Python?
You have seven realistic options, and they differ mostly in where the part that must hold a beat ends up living. You can write one Python script and let the machine be simple enough to deserve it. You can put the beat in the hardware, buying a motor controller or a smart actuator that runs its own loop while your Python sends goals. You can write Python nodes on ROS 2, which ships a Python client library and brings the largest body of existing robotics code anywhere. You can split the machine into a Python program and a compiled loop that share data directly, which is what HORUS is for: an open-source real-time robotics middleware for Rust, Python and C++ where the three languages share the same shared-memory ring buffers, so messages between processes on one machine are not serialised. You can run Python on a microcontroller board. You can write one small compiled extension yourself. Or you can put the safety layer in a physical circuit and keep everything else in Python.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| One Python script | Anyone bringing a first machine to life | Python and your device libraries | The machine is small, slow and watched by a person | Two things must keep time at once |
| Python plus a vendor motion controller | Builders who want motion without writing the fast part | The vendor's API and where it stops | The beat can live in firmware you did not write | The behaviour you need is below what the vendor exposes |
| ROS 2 with Python nodes | Teams needing navigation, drivers or borrowed packages | Linux, workspaces, launch files, message types | The robot's value is code other people already wrote | One board, one loop, and nobody to maintain a workspace |
| HORUS | Python-first teams with a loop that must not wait for Python | Your message shapes and how your loops are scheduled | Python and a compiled loop must share sensor data on one board | Navigation packages are the whole project |
| Python on a microcontroller board | Hobbyists, classrooms and small kit builds | Wiring, and the limits of the board | The entire machine fits on one small board | The machine carries a camera and a model |
| Python plus one compiled extension | Builders with a single hot piece and appetite to own it | Enough C or Rust for one file, plus its build tooling | Exactly one part of the machine needs to be fast | Nobody wants to maintain a second toolchain |
| Python plus a hardware safety circuit | Anyone running a machine near people | Basic wiring and what your machine does without power | Stopping must not depend on software at all | The machine cannot be stopped mechanically |
What should you pick if Python is the only language you know well?
Push the timing-critical work onto hardware that already does it, and keep writing Python above that line. A motor controller that accepts a target position and runs its own loop turns the hardest part of robot software into a purchase, and that is a legitimate engineering decision rather than a cheat. What you should learn instead of a second language is how to stop your own code interrupting itself: keep file writes, logging and anything that loads from disk out of the loop that moves the machine, and do not let per-frame work grow as the program runs. That skill transfers to every language you may learn later, and most people who rewrite in C++ without learning it get a faster program with the same stutter. The advantage of staying in Python is that you keep changing the robot quickly, which is worth more in the first months than any speed you gain by rewriting. Learn a second language when you can name the one file that needs it, as covered in what most language guides get wrong.
What hardware makes a Python-only robot realistic?
A Python-only robot is realistic when the hardware absorbs the timing you cannot promise in software. The shopping list is specific. Motor controllers or smart actuators that take a target and close their own loop, so a late message from you means a slightly late move rather than a fallen machine. A mobile base that accepts a velocity and keeps driving until told otherwise. Cameras that stamp their own frames, so you can tell a stale picture from a still scene. A stop circuit that removes power without consulting any software at all. A computer with room to spare, so that an occasional pause is absorbed instead of showing up in the motion. What makes Python-only hard is the opposite list: raw motor bridges wired straight to pins, anything that balances, direct force or torque control against a surface, and machines that must read many sensors in lockstep. Those are not arguments against Python for the rest of your robot. They are arguments for buying the part of the machine that has to be strict about time.
What if you need something working in a few weeks?
Write Python, buy hardware that already holds the beat, and do not start learning a second language on a deadline. A few weeks is enough to find out what your machine does when things go wrong, and not enough to become competent in a new toolchain. The version that works looks like this: a base or an arm with a supported Python interface, one script, a physical stop within reach, and a log written outside the loop so you can read afterwards what the machine thought was happening. The version that fails starts with a rewrite decided before anybody knew which part was at fault, continues through a week of build errors, and arrives at the demonstration with a program that compiles beautifully and has never picked anything up. If the date is real, spend the first days making the machine move without any clever code involved, and add the clever part once the boring part is dependable.
What if you have never written a program that runs for days?
Assume that a program which has run for ten minutes tells you almost nothing about what it will do overnight, and build for that from the first week. Robot code fails differently over time, and the failures are dull rather than dramatic. Memory creeps up because something appends to a list that is never emptied. A file handle is opened per image and never closed. A queue fills because one part of the program fell behind and nobody noticed. A camera reconnects after a glitch with different settings than it had before. Clocks drift apart between devices. None of these need a second language to fix, and all of them need habits: one place where the program can be told to stop cleanly, a heartbeat that says the loop is still turning, and a timestamp on every reading so that stale data is visible as stale. The teams who add these later usually add them the morning after the machine stopped in the night and nobody could say why.
What do Python-first builders try first, and why does it stop working?
Nearly everyone starts with one script that reads a sensor, decides something and commands a motor in a single sequence, and that arrangement stops working the moment two things must happen at different rhythms. Starting there is right: a single file teaches you more about your hardware than a month of architecture would. The way it breaks is consistent. Everything sits in one sequence, so the slowest step sets the pace for all the others, and the pace is not steady. Threads come next, and then the discovery that Python threads do not run their Python at the same time as each other, so the loop is no smoother than before. Then processes, which genuinely help, followed by the surprise that sending pictures between processes copies them, and the copying is what shows up in the motion. That is the fork in the road: either the fast part moves off this computer entirely, or the two programs need a way to look at the same data without one handing it to the other.
What changes as the robot gets more demanding?
The demands arrive in a predictable order, and Python survives the first two more comfortably than the third. First the sensors multiply: one camera becomes two cameras, wheel encoders and an inertial sensor, each producing readings at its own pace, and suddenly it matters which reading belongs with which. Second the rhythms multiply: something has to run steadily while something else takes as long as it takes, and the two must not be in the same sequence. Third, the machine has to run without anybody watching, and that is the step that changes the work. A supervised robot has a person as its recovery mechanism, and an unattended one has whatever you wrote. Watchdogs, restarts, logs somebody can read the next morning, and a definition of what the machine should do when a sensor goes quiet all become the job. Notice that none of these three steps is about language. A team can pass all three in Python and fail all three in C++, and the difference is structure rather than syntax.
What do you give up by staying in Python?
You give up the ability to promise that a specific thing will happen at a specific moment, and most machines never needed that promise. The runtime can pause to tidy memory when it decides to, your code can be interrupted between any two lines, and the language offers no way to say never later than this. For an arm picking parts off a table, none of that is visible. For a machine holding itself upright, it is the whole problem. You also give up a handful of libraries that ship only a C++ interface, though fewer than the reputation suggests, and you give up the smallest embedded targets where a full interpreter does not fit. There is a quieter cost: some mistakes appear only when the machine is running, because a branch nobody exercised contains a name that does not exist. Tests and type annotations reduce that, and neither of them requires you to leave Python. Weigh these against changing your robot's behaviour in an afternoon, which is what you keep.
When is ROS 2 the better choice?
ROS 2 is the better choice when the robot has to map a building, navigate to a goal, or use drivers that other people already wrote, and the Python client library means choosing ROS 2 does not force you into C++. The navigation and mapping packages are years of work you will not reproduce alongside everything else you are doing. ROS 2 also wins when your sensor ships a ROS 2 driver and nothing else, when the machine spans more than one computer, and when the tooling for inspecting what happened after the fact matters more to you than anything else on the list. HORUS is not the answer for those projects, and picking it there means rebuilding for free what you could have inherited. The place ROS 2 asks for care is the same place every framework does: a Python node sitting directly between a camera and a motor, with the motion depending on that node keeping up. Whether you need ROS 2 at all is worth asking honestly, and the answer is often yes.
Is Python too slow to control a robot?
No, and here is why: the arithmetic inside a control loop is tiny, and the heavy work in a robot program is already happening inside compiled libraries that Python is merely calling. A loop that reads a position, subtracts, multiplies and writes a command is not where your time goes. The genuine issue is not the average pace but the occasional pause, and those two complaints get mixed together in every forum thread on the subject. A faster language fixes the first and only partly helps the second, because a pause caused by your program writing a log file, loading a model or growing a list is still there after the rewrite. Tell them apart by watching the machine rather than reading about it: motion that lags consistently is a speed problem, and motion that is smooth and then jerks is a pause problem. The distinction is explored further in whether Python is fast enough for robot control, and getting it right saves people entire quarters.
Will rewriting everything in C++ fix the stutter?
Partly, but not the way you think. A rewrite removes one source of pauses and leaves every other one exactly where it was. The operating system still decides when your program runs. The camera still hands over frames when it feels like it rather than when you asked. The network still hiccups, the disk still makes you wait, and a loop that stops to write a file stops just as long in a compiled language. Teams who rewrite without first finding the cause often report that the stutter moved rather than left, which is a demoralising outcome after three months of work. What actually fixes it is structural: name the one thing that must keep a beat, give it its own process, keep everything expensive out of that process, and let it receive data without waiting for another program to hand it over. Once that structure exists, the language of the fast part becomes a much smaller decision, and it is sometimes still Python.
How do you decide whether Python alone will carry your robot?
Ask what happens to your machine when a single command arrives late, and let the answer make the decision. If the answer is that nothing visible happens, write the whole robot in Python and stop reading articles like this one. If the answer is a small jerk you can live with, keep Python and buy a controller board that holds the beat for you. If the answer is that the robot falls over, the tool digs into the part, or somebody could be hurt, then that particular loop does not belong in any program you are able to interrupt, and it should live in firmware or in a circuit while everything above it stays Python. Then ask a second question: how many separate programs need to look at the same camera frame on one computer? If the answer is one, a script is enough. If it is two or more, you have a plumbing decision to make, and that is the same fork described in embodied AI versus agentic AI.
Decide by situation rather than by reputation:
- If a person watches the machine and it moves at human pace -> Python everywhere, because nothing in it is judged by its worst moment.
- If the robot falls over when a command is late -> a controller board or firmware for that loop, because no interpreted program should be holding a machine upright.
- If two programs on one computer must share camera frames -> a shared-memory middleware, because copying pictures between them is what you will see in the motion.
- If the robot must map a building and navigate -> ROS 2 with Python nodes, because the packages exist and rewriting them is not your project.
- If you cannot yet say which part is late -> measure before rewriting, because most stutters come from something inside the loop that should not be there.
When two options stay close, weigh them on the five axes of the HORUS Fit Framework: ecosystem size, setup effort, team size fit, deployment target, and licence. Take whichever loses on the fewest: five honest questions about your situation rather than about the software, with no scores attached. If you keep landing on one machine where Python does the thinking and something beside it must not wait, star HORUS on GitHub so it is in your list when you start building.