Skip to content

Commit

Permalink
Add demo notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
minrk committed Mar 9, 2016
1 parent a3be844 commit ea70e0e
Showing 1 changed file with 224 additions and 0 deletions.
224 changes: 224 additions & 0 deletions Demo.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Capturing C-level stdout/stderr with `wurlitzer`\n",
"\n",
"Sometimes in Python you are calling some C code.\n",
"Sometimes that C code makes calls to `printf`,\n",
"or otherwise writes to the stdout/stderr of the process."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import ctypes\n",
"libc = ctypes.CDLL(None)\n",
"\n",
"try:\n",
" c_stderr_p = ctypes.c_void_p.in_dll(libc, 'stderr')\n",
"except ValueError:\n",
" # libc.stdout is has a funny name on OS X\n",
" c_stderr_p = ctypes.c_void_p.in_dll(libc, '__stderrp')\n",
"\n",
"\n",
"def printf(msg):\n",
" \"\"\"Call C printf\"\"\"\n",
" libc.printf((msg + '\\n').encode('utf8'))\n",
"\n",
"def printf_err(msg):\n",
" \"\"\"Cal C fprintf on stderr\"\"\"\n",
" libc.fprintf(c_stderr_p, (msg + '\\n').encode('utf8'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"IPython forwards the Python-level `sys.stdout` and `sys.stderr`,\n",
"but it leaves the process-level file descriptors that C code will write to untouched.\n",
"That means that in a context like this notebook, these functions will print to the terminal, because they are not captured:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"printf(\"Hello?\")\n",
"printf_err(\"Stderr? Anybody?\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With wurlitzer, we can capture these C-level functions:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from wurlitzer import pipes, sys_pipes, STDOUT, PIPE"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"with pipes() as (stdout, stderr):\n",
" printf(\"Hello, stdout!\")\n",
" printf_err(\"Hello, stderr!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and redisplay them if we like:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello, stdout!\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Hello, stderr!\n"
]
}
],
"source": [
"import sys\n",
"sys.stdout.write(stdout.read())\n",
"sys.stderr.write(stderr.read())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some tools, such as the IPython kernel for Jupyter,\n",
"capture the Python-level `sys.stdout` and `sys.stderr` and forward them somewhere.\n",
"In the case of Jupyter, this is over a network socket, so that it ends up in the browser.\n",
"\n",
"If we know that's going on, we can easily hook up the C outputs to the Python-forwarded ones with a single call:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello from C, 0!\n",
"Hello from C, 1!\n",
"Hello from C, 2!\n",
"Hello from C, 3!\n",
"Hello from C, 4!\n"
]
}
],
"source": [
"import time\n",
"\n",
"with sys_pipes():\n",
" for i in range(5):\n",
" time.sleep(1)\n",
" printf(\"Hello from C, %i!\" % i)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also capture the pipes to any writeable streams, such as a `StringIO` object:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello, stdout!\n",
"Hello, stderr!\n",
"\n"
]
}
],
"source": [
"import io\n",
"\n",
"stdout = io.StringIO()\n",
"with pipes(stdout=stdout, stderr=STDOUT):\n",
" printf(\"Hello, stdout!\")\n",
" printf_err(\"Hello, stderr!\")\n",
"\n",
"print(stdout.getvalue())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

0 comments on commit ea70e0e

Please sign in to comment.