I want to use the power of Matplotlib (fantastic python graphing library) in an existing php application of mine. Before embarking on the specifics of my application, I tried to get a super simple demo up and running, which proved far more difficult than I had expected.

This is my very simple matplotlib example:

#!/usr/bin/env python import sys import matplotlib matplotlib.use('Agg') from pylab import * plot([1,2,3]) savefig(sys.stdout)

I then tried to call it from a simply PHP script using

exec('python my_python_script.py', $output);

Each line outputted by python to stdout goes into an element of the array $output. One simply prints each element followed by a carriage return from PHP to the browser.

However the output was corrupted and would not render as a png file. Running the python script from the command line and piping to a file gave a valid image though. Turning off the png image headers gave me a page of machine code, which looked identical to what I got by using file_get_contents to stream the valid png image that I previously piped from the command line.

In desperation, I saved each file from my browser and dropped them into a hex editor. Here, I found that the genuine png file contained a line feed character (0x0D) just after the first line, that my corrupt file did not. This caused a 2 character offset to occur to the rest of the file, hence the corruption.

Hex Comparison

If you know why this occurs, please let me know. In the mean time, here is my working PHP script complete with a bandaid solution:

<?php 
header("Content-type: image/png");
$stuff = exec('python python_graph.py', $output);
foreach($output as $key=>$value){
    if($key==1)
        print chr(0x0D); //Newline feed after PNG declaration
    if($key>0)
        print "\n";
    print $value;
}
?>

And here is the image in all its glory.

python_graph

3 thoughts on “Using matplotlib in PHP”

  1. Found out while doing something almost identical to you (WHY does PHP have no decent graphing libraries) – PHP’s exec is NOT binary safe. Shell_exec might be, but proc_open certainly is. A code example below (pretty much straight from the PHP docs):

    $descriptorspec = array(
    0 => array(“pipe”, “r”), // stdin is a pipe that the child will read from
    1 => array(“pipe”, “w”), // stdout is a pipe that the child will write to
    );
    $process = proc_open(dirname(__FILE__).”/Graph.py”, $descriptorspec, $pipes);
    if (is_resource($process)){
    fwrite($pipes[0], json_encode($this->output, JSON_PRETTY_PRINT));
    fclose($pipes[0]);
    header (‘Content-Type: image/png’);
    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $return_value = proc_close($process);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *