The Python client
It speaks to the same tool layer as the CLI and the MCP server, by spawning
mobium pipe, so the mobium binary has to be on PATH or named by
MOBIUM_BIN_PATH. The quick start goes from nothing to a
running script.
Install
pip install "mobium @ git+https://github.com/mobiumdev/mobium.git#subdirectory=clients/python"
Connect
from mobium import start
with start(platform="android", app="com.android.settings") as device:
for el in device.map():
print(el.ref, el.label)
device below is what start() or connect() returned: a mobium.Device.
Every tool, by method
Connecting, ending, and errors
connect
def connect(device: str | None=None, driver: str | None=None, binary: str | None=None, call_timeout: float | None=None, session: str | None=None) -> 'Device'
Start a mobium session.
device: serial or UDID, when more than one is running. driver: "uiautomator2" (default), "uiautomator", or "wda". call_timeout: the longest, in seconds, any one call may take before the connection is given up, the handshake included. None, the default, waits as long as it takes: the first session on an iPhone builds WebDriverAgent, which takes minutes. A call that runs out ends the connection -- a late answer would be read as the next call's -- and every call after raises, saying so; connect again. Set it well above the longest wait_for timeout you use. session: a daemon of this connection's own, by name, as MOBIUM_SESSION sets one. One daemon serves one call at a time across every device, so parallel runs on different devices should each name one: sharing, an emulator's calls waited behind a simulator's, 22.3s against 0.3s. Keep it short; it is part of a socket path.
Connect without opening a session first
import mobium
device = mobium.connect()
print(device.current())
device.close()
Pick one of several devices, with a daemon of its own
from mobium import connect
device = connect(device="emulator-5554", session="pixel")
close
def close() -> None
def close() -> None
Close the connection. The device's session lives in the daemon and stays open, for the next connect() or the CLI; quit() ends it.
Close the connection and leave the session open
device = mobium.connect()
try:
print(device.current())
finally:
device.close()
Device
class Device
A connected device or simulator.
Use a device in a with block, which quits on the way out
with mobium.start(platform="android", app="com.android.settings") as device:
for el in device.map():
print(el.ref, el.label)
Element
class Element
One actionable element on screen.
Read an element's fields
for el in device.map():
print(el.ref, el.label, el.role, el.locator, el.checked)
Bounds
class Bounds
An on-screen rectangle in device pixels, on both platforms.
Find where an element is on screen
el = device.find("text=System")[0]
print(el.bounds.center, el.bounds.width, el.bounds.height)
DeviceInfo
class DeviceInfo
One attached device or simulator.
Tell emulators from real hardware
for info in device.devices():
kind = "emulator" if info.emulator else "device"
print(info.id, info.model, kind)
Session
class Session
What start() opened: the device and how it is driven.
See what start() opened
device = mobium.start(platform="ios")
print(device.session.device, device.session.driver, device.session.reused)
MobiumError
class MobiumError(RuntimeError)
A tool reported that it could not do what was asked.
Also the exception for a code this client does not recognize, and for a
daemon too old to send codes at all — code is then "error".
Catch any failure, and read its code and remedy
try:
device.tap("text=Continue")
except mobium.MobiumError as e:
print(e.code, e.message)
print(e.remedy)
NoSuchElementError
class NoSuchElementError(MobiumError)
A locator or ref matched nothing on screen. Worth scrolling for.
Scroll for an element that is not on screen
from mobium import NoSuchElementError
try:
device.tap("text=Continue")
except NoSuchElementError:
device.scroll_to("text=Continue")
AmbiguousLocatorError
class AmbiguousLocatorError(MobiumError)
A locator matched more than one element. Narrow it; Mobium never guesses.
Fall back to a ref when a locator matches more than one element
try:
device.tap("text=OK")
except mobium.AmbiguousLocatorError:
device.tap(device.find("text=OK")[0].ref)
TimedOutError
class TimedOutError(MobiumError)
A wait ran out. Named TimedOut so it does not shadow the builtin TimeoutError.
Handle a wait that never came true
try:
device.wait_for("text=Welcome back", timeout_ms=5000)
except mobium.TimedOutError as e:
print("still not there:", e.message)
UnsupportedError
class UnsupportedError(MobiumError)
This driver or platform cannot do it, and says why. Retrying cannot help.
Skip what a platform cannot do
try:
device.press("back")
except mobium.UnsupportedError:
device.tap("label=Back") # iOS has no back button
NoDeviceError
class NoDeviceError(MobiumError)
Nothing to drive: no device matches, or none is connected.
Report that no device is running
try:
device = mobium.start()
except mobium.NoDeviceError as e:
print(e.remedy)
DeviceNotReadyError
class DeviceNotReadyError(MobiumError)
The device is there and cannot be driven yet — locked, not trusted, Developer Mode off.
Unlock a device that is not ready
try:
device.launch("com.android.settings")
except mobium.DeviceNotReadyError:
device.set_screen_locked(False)
device.launch("com.android.settings")
NotConfirmedError
class NotConfirmedError(MobiumError)
The command reported success and reading the state back disagreed.
Notice an action the device did not confirm
try:
device.timezone("Asia/Tokyo")
except mobium.NotConfirmedError as e:
print("not applied:", e.message)
NoSuchContextError
class NoSuchContextError(MobiumError)
A WebView context that is not there.
Handle a WebView that is not there
try:
device.context("WEBVIEW_com.example.shop")
except mobium.NoSuchContextError:
print(device.contexts())
NoSuchAlertError
class NoSuchAlertError(MobiumError)
A dialog was expected and none is on screen.
Answer a dialog only if one is up
try:
device.answer_alert(accept=False)
except mobium.NoSuchAlertError:
pass
ElementNotReachableError
class ElementNotReachableError(MobiumError)
The element was found and cannot be touched where it is — usually off screen.
Handle an element that exists but cannot be touched
try:
device.tap("text=Buy")
except mobium.ElementNotReachableError as e:
print(e.details)
InvalidArgumentError
class InvalidArgumentError(MobiumError)
The request itself is wrong.
Catch an argument the tool refused
try:
device.set_orientation("left")
except mobium.InvalidArgumentError as e:
print(e.message)
ToolchainMissingError
class ToolchainMissingError(MobiumError)
Something on this machine is missing: adb, Xcode, a signing certificate.
Point at doctor when a tool is missing
try:
device = mobium.start(platform="ios")
except mobium.ToolchainMissingError as e:
print(e.remedy)
DeviceServerError
class DeviceServerError(MobiumError)
The device side failed: a device server, or adb, simctl, devicectl, lockdown.
A device server's own W3C code, when it sent one, is in details["w3c"].
Read the device server's own code
try:
device.tap("@e2")
except mobium.DeviceServerError as e:
print(e.details.get("w3c"))
InternalError
class InternalError(MobiumError)
A bug in Mobium.
Retry only what can succeed again
try:
device.map()
except mobium.InternalError as e:
if e.retryable:
device.map()
Types
| Type | What it is |
|---|---|
Bounds | An on-screen rectangle in device pixels, on both platforms. |
Element | One actionable element on screen. |
DeviceInfo | One attached device or simulator. |
Session | What start() opened: the device and how it is driven. |
Device | A connected device or simulator. |
MobiumError | A tool reported that it could not do what was asked. |
NoDeviceError | Nothing to drive: no device matches, or none is connected. |
DeviceNotReadyError | The device is there and cannot be driven yet — locked, not trusted, Developer Mode off. |
ToolchainMissingError | Something on this machine is missing: adb, Xcode, a signing certificate. |
NoSuchElementError | A locator or ref matched nothing on screen. |
AmbiguousLocatorError | A locator matched more than one element. |
ElementNotReachableError | The element was found and cannot be touched where it is — usually off screen. |
NoSuchContextError | A WebView context that is not there. |
NoSuchAlertError | A dialog was expected and none is on screen. |
UnsupportedError | This driver or platform cannot do it, and says why. |
NotConfirmedError | The command reported success and reading the state back disagreed. |
TimedOutError | A wait ran out. |
InvalidArgumentError | The request itself is wrong. |
DeviceServerError | The device side failed: a device server, or adb, simctl, devicectl, lockdown. |
InternalError | A bug in Mobium. |