gradosevic gradosevic - 2 months ago 19
PHP Question

Python argparse does not parse images with wildcard

I use this library https://github.com/cmusatyalab/openface for image comparison.

I have downloaded Docker container with preinstalled environment.

I start the container and I'm accessing this file:
https://github.com/cmusatyalab/openface/blob/master/demos/compare.py

with this command:


./demos/compare.py images/examples/{lennon*,clapton*}


(check http://cmusatyalab.github.io/openface/demo-2-comparison/ if you want)

It works fine when I execute the command directly from Docker terminal. Parsed arguments look like this:

Namespace(dlibFacePredictor='/root/openface/demos/../models/dlib/shape_predictor_68_face_landmarks.dat', imgDim=96, imgs=['images/examples/lennon-1.jpg', 'images/examples/lennon-2.jpg', 'images/examples/clapton-1.jpg', 'images/examples/clapton-2.jpg'],
networkModel='/root/openface/demos/../models/openface/nn4.small2.v1.t7', verbose=False)


The problem is when I execute the same command from PHP file (I start simple PHP web server to access this script from host machine). PHP code:


echo shell_exec('./demos/compare.py
images/examples/{lennon*,clapton*}')


Parsed arguments look now like this:

Namespace(dlibFacePredictor='/root/openface/demos/../models/dlib/shape_predictor_68_face_landmarks.dat', imgDim=96, imgs=['images/examples/{lennon*,clapton*}'],
networkModel='/root/openface/demos/../models/openface/nn4.small2.v1.t7', verbose=False)


BOTTOMLINE:

When script is executed directly, imgs argument is parsed correctly

imgs=['images/examples/lennon-1.jpg', 'images/examples/lennon-2.jpg', 'images/examples/clapton-1.jpg', 'images/examples/clapton-2.jpg']


When script is executed from PHP script, imgs argument is not correctly parsed:

imgs=['images/examples/{lennon*,clapton*}']


Code:

import time

start = time.time()

import argparse
import cv2
import itertools
import os

import numpy as np
np.set_printoptions(precision=2)

import openface

fileDir = os.path.dirname(os.path.realpath(__file__))
modelDir = os.path.join(fileDir, '..', 'models')
dlibModelDir = os.path.join(modelDir, 'dlib')
openfaceModelDir = os.path.join(modelDir, 'openface')

parser = argparse.ArgumentParser()

parser.add_argument('imgs', type=str, nargs='+', help="Input images.")
parser.add_argument('--dlibFacePredictor', type=str, help="Path to dlib's face predictor.",
default=os.path.join(dlibModelDir, "shape_predictor_68_face_landmarks.dat"))
parser.add_argument('--networkModel', type=str, help="Path to Torch network model.",
default=os.path.join(openfaceModelDir, 'nn4.small2.v1.t7'))
parser.add_argument('--imgDim', type=int,
help="Default image dimension.", default=96)
parser.add_argument('--verbose', action='store_true')

args = parser.parse_args()


Any idea why this happens? Thanks.

Answer

Neither python nor argparse do any wildcard expansion on the argv list passed in from the parent process. Instead, this is handled by the shell.

It'll depend on the shell wether or not your style of expansion is even supported. Evidently, the shell that shell_exec() spawns (usually /bin/sh) does not support bash-style brace expansion. Instead, the wildcards are passed through to Python un-expanded.

Simplify the wildcard style by relying on * expansion only:

echo shell_exec('./demos/compare.py images/examples/lennon* images/examples/clapton*')
Comments