r2pipe for Python
Interact with radare2 using the #!pipe command or in standalone scripts that communicate with local or remote r2 via pipe, tcp or http.
Installation
$ pip install r2pipe
or
$ pip3 install r2pipe
Usage example:
import r2pipe
r2 = r2pipe.open("/bin/ls")
r2.cmd('aa')
print(r2.cmd("afl"))
print(r2.cmdj("aflj")) # evaluates JSONs and returns an object
print(r2.cmdj("ij")["core"]["format"]) # shows file format
r2.quit()
Structured commands (r2pipe2)
cmd2() accepts boolean trim and json options. trim=True strips output
whitespace; json=True asks radare2 to embed the command's JSON output in
the response's res field. cmd2j() defaults both options to True, and
explicit False values override those defaults.
with r2pipe.open("-", flags=["-N"]) as r2:
print(r2.cmd2("?e hello", trim=True).res) # "hello"
print(r2.cmd2("ij", json=True).res.core.file)
print(r2.cmd2j("?e hello", json=False, trim=False).res) # "hello\n"
Both methods accept callback=..., which receives the raw response string
before Python parses the JSON. Callbacks are handled in Python and are never
included in the request JSON. Synchronous call(), cmd(), cmdj(), and
cmdJ() also support callbacks. Unknown r2pipe2 keywords, non-boolean flags,
and callbacks that are neither callable nor None raise TypeError before
execution. call() accepts only the optional callback keyword.
Asyncio
Import the async client to await commands inside an event loop:
import asyncio
from r2pipe.open_async import open as async_open
async def main():
async with async_open("/bin/ls", flags=["-N"]) as r2:
reply = await r2.cmd2j("ij")
print(reply.res.core.file)
print(await r2.cmd("afl"))
asyncio.run(main())
cmd, cmdj, cmdJ, call, cmd2, and cmd2j return awaitables inside
the client's event loop. Outside a running loop, the async client keeps its
existing blocking behavior. A client created before starting the event loop
can be used inside it; once commands have run, use that same loop for the
rest of the session. Embedded #!pipe and r2lang commands retain their
blocking behavior.
Native ccall:// sessions also support these awaitable methods. Each session
runs core creation, commands, and cleanup on one dedicated worker thread so
native calls leave the event loop responsive.
Use async with or await r2.close() / await r2.quit() to clean up. Closing
keeps the caller's event loop open. Commands on one client run in sequence,
including commands submitted with asyncio.gather. Canceling a command that
has already started lets its response finish draining before the next command
runs; the command may still change radare2 state. Closing waits for these
started commands and rejects commands still waiting to run. Callbacks receive
the raw response before JSON parsing, as with blocking calls.
Async HTTP/TCP connection failures, read errors, and response timeouts raise exceptions from the command call (or its awaitable). Success callbacks are not called for failed commands; errors are not returned as response strings.