pythonsubprocessogr

Python subprocess formulation


I have been experimenting with Python's subprocess module. I wish to emulate the following, successful command:

Command line:

ogr2ogr -f GeoJSON -clipsrc cutting.json output.json input.json

Python implementation:

import subprocess
subprocess.call(["ogr2ogr", "-f", "GeoJSON", "-clipsrc", "cutting.json", "output.json", "input.json"], shell=True)

However, the python script outputs: FAILURE: no target datasource provided

From the documentation, I can see that the syntax is correct and that I am specifying the source and destination datasources in the correct order. Of course, since it works on the command line I am inclined to think the data orientation is correct. Am I calling the subprocess incorrectly?

For reference, ogr2ogr usage:

Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
               [-select field_list] [-where restricted_where]
               [-progress] [-sql <sql statement>] [-dialect dialect]
               [-preserve_fid] [-fid FID]
               [-spat xmin ymin xmax ymax] [-geomfield field]
               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
               dst_datasource_name src_datasource_name
               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3|layer_dim] [layer [layer ...]]

Advanced options :
               [-gt n]
               [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]
               [-clipsrcsql sql_statement] [-clipsrclayer layer]
               [-clipsrcwhere expression]
               [-clipdst [xmin ymin xmax ymax]|WKT|datasource]
               [-clipdstsql sql_statement] [-clipdstlayer layer]
               [-clipdstwhere expression]
               [-wrapdateline][-datelineoffset val]
               [[-simplify tolerance] | [-segmentize max_dist]]
               [-addfields]
               [-relaxedFieldNameMatch]
               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]
               [-fieldmap identity | index1[,index2]*]
               [-splitlistfields] [-maxsubfields val]
               [-explodecollections] [-zfield field_name]
               [-gcp pixel line easting northing [elevation]]* [-order n | -tps]

Solution

  • I, personally, use something like the following on *nix-based machines to completely dispatch a call from a python script. Maybe it helps you (or you can tailor it to suit your needs).

    import os, subprocess, time
    name = 'ogr2ogr_{}'.format(time.time())
    call = ['nohup', 'ogr2ogr', '-f', 'GeoJSON', '-clipsrc', 
            'cutting.json', 'output.json', 'input.json']
    o_std = open(os.path.join('/my/log/dir', '{}.log'.format(name)), 'w')
    o_err = open(os.path.join('/my/log/dir', '{}.err'.format(name)), 'w')
    r = subprocess.Popen(call, stdout=o_std, stderr=o_err, preexec_fn=os.setpgrp)
    

    If you don't want to dispatch the subprocess, just remove the nohup list item and don't set os.setpgrp as preexec_fn.