Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing dictionaries to a Python script through the command line

How can I pass a dictionary to a python script from another python script over the command line? I use subprocess to call the second script.

The options I've come to are:
I) Build a module to parse a dictionary from a string (more in-depth than I had hoped to go).
II) Use a temporary file to write a pickle, and pass the file's name as an argument
III) Don't allow dictionaries, but handle key/value pairs (that is "prog.py keya valuea keyb valub")

The solution does not have to be user-friendly, but does need to be program friendly. The second program must be run as a separate process, due to security and resource concerns.

like image 553
Chris Adams Avatar asked Sep 23 '10 16:09

Chris Adams


4 Answers

Have you looked at the pickle module to pass the data over stdout/stdin?

Example:

knights.py:

import pickle
import sys

desires = {'say': 'ni', 'obtain': 'shrubbery'}
pickle.dump(desires, sys.stdout)

roundtable.py:

import pickle
import sys

knightsRequest = pickle.load(sys.stdin)
for req in knightsRequest:
    print "The knights %s %s." % (req, knightsRequest[req])

Usage and output:

$ python knights.py | python roundtable.py
The knights say ni.
The knights obtain shrubbery.
like image 121
Mike DeSimone Avatar answered Oct 13 '22 17:10

Mike DeSimone


Aside from pickle, another option is ast.literal_eval, if your dictionaries only contain Python primitives.

>>> d = {3: 9, 'apple': 'orange'}
>>> s = str(d)
>>> s
"{3: 9, 'apple': 'orange'}"
>>> import ast
>>> x = ast.literal_eval(s)
>>> x
{3: 9, 'apple': 'orange'}
like image 39
FogleBird Avatar answered Oct 13 '22 17:10

FogleBird


If you don't need a too terribly complicated data structure, might I recommend simplejson? It's available as a built-in module (called json) in Python 2.6 and later.

like image 43
Ross Light Avatar answered Oct 13 '22 17:10

Ross Light


If what's in the dictionary (both keys and values) can be represented as strings, you should be able to pass it as a string argument to the second script which can recreate it.

d = {'a':1,'b':2}

d == eval(repr(d), None)

>>>True

Edit: Here's a slightly more involved example showing its use with a simple custom class:

class MyClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __repr__(self):
        return 'MyClass(%r, %r)' % (self.a, self.b)
    def __eq__(self, other):
        return (self.a == other.a) and (self.b == other.b)

d = {'foo':42, 'bar': MyClass(17,'astring') }

print 'd:', d
print 'repr(d):', repr(d)
print "d == eval(repr(d), {'MyClass':MyClass})?:", \
      d == eval(repr(d), {'MyClass':MyClass})

# outputs:
# d: {'foo': 42, 'bar': MyClass(17, 'astring')}
# repr(d): {'foo': 42, 'bar': MyClass(17, 'astring')}
# d == eval(repr(d), {'MyClass':MyClass})?: True
like image 2
martineau Avatar answered Oct 13 '22 17:10

martineau