Обработка аргументов программы Python в файле json - PullRequest
0 голосов
/ 31 декабря 2010

Я новичок в Python.Я хотел бы совет по обработке параметров программы, которые находятся в файле в формате JSON.В настоящее время я делаю что-то вроде того, что показано ниже, однако это кажется слишком многословным, и идея набирать одну и ту же буквальную строку несколько раз (иногда с черточками, а иногда с подчеркиванием) кажется ювенильной - подверженной ошибкам - вонючей ...-) (У меня есть еще много параметров!)

#!/usr/bin/env python
import sys
import os
import json                 ## for control file parsing

# control parameters
mpi_nodes = 1
cluster_size = None
initial_cutoff = None
# ...

#process the arguments
if len(sys.argv) != 2:
    raise Exception(
        """Usage:
                run_foo <controls.json>
            Where:
                <control.json> is a dictionary of run parameters
        """
    )

# We expect a .json file with our parameters
controlsFileName = sys.argv[1]
err = ""
err += "" #validateFileArgument(controlsFileName, exists=True)

# read in the control parameters from the .json file
try:
    controls = json.load(open(controlsFileName, "r"))
except:
    err +=  "Could not process the file '" + controlsFileName + "'!\n"

# check each control parameter. The first one is optional
if "mpi-nodes" in controls:
    mpi_nodes = controls["mpi-nodes"]
else:
    mpi_nodes = controls["mpi-nodes"] = 1

if "cluster-size" in controls:
    cluster_size = controls["cluster-size"]
else:
    err += "Missing control definition for \"cluster-size\".\n"

if "initial-cutoff" in controls:
    initial_cutoff = controls["initial-cutoff"]
else:
    err += "Missing control definition for \"initial-cutoff\".\n"

# ...

# Quit if any of these things were not true
if len(err) > 0:
    print err
    exit()

#...

Это работает, но, похоже, должен быть лучший способ.Я застрял с требованиями использовать файл JSON и использовать имена параметров через дефис.Любые идеи?

Я искал что-то с более статической привязкой.Возможно, это так же хорошо, как и получается.

Ответы [ 4 ]

2 голосов
/ 31 декабря 2010

Обычно мы делаем такие вещи.

def get_parameters( some_file_name ):
    source= json.loads( some_file_name )
    return dict(
        mpi_nodes= source.get('mpi-nodes',1),
        cluster_size= source['cluster-size'],
        initial_cutoff = source['initial-cutoff'],
    )

 controlsFileName= sys.argv[1]
 try:
     params = get_parameters( controlsFileName )
 except IOError:
     print "Could not process the file '{0}'!".format( controlsFileName )
     sys.exit( 1 )
 except KeyError, e:
     print "Missing control definition for '{0}'.".format( e.message )
     sys.exit( 2 )

A конец params['mpi_nodes'] имеет значение mpi_nodes

Если вы хотите простую переменную, вы делаете это. mpi_nodes = params['mpi_nodes']

Если вы хотите именованный кортеж, измените get_parameters следующим образом

def get_parameters( some_file_name ):
    Parameters= namedtuple( 'Parameters', 'mpi_nodes, cluster_size, initial_cutoff' )
    return Parameters( source.get('mpi-nodes',1),
        source['cluster-size'],
        source['initial-cutoff'],
    )

Я не знаю, найдете ли вы это лучше или нет.

1 голос
/ 31 декабря 2010

Я узнал кое-что из всех этих ответов - спасибо!Я хотел бы получить отзыв о моем подходе, который включает в себя что-то из каждого предложения.В дополнение к условиям, налагаемым клиентом, я хочу что-то:

1), которое довольно очевидно для использования и отладки 2), которое легко поддерживать и изменять

Я решил включитьstr.replace, namedtuple и globals (), создающий именованный кортеж ControlParameters в пространстве имен globals ().

#!/usr/bin/env python

import sys
import os
import collections
import json                 


def get_parameters(parameters_file_name ):
    """
    Access all of the control parameters from the json filename given. A
    variable of type namedtuple named "ControlParameters" is injected
    into the global namespace. Parameter validation is not performed. Both
    the names and the defaults, if any, are defined herein. Parameters not
    found in the json file will get values of None.

    Parameter usage example: ControlParameters.cluster_size
    """
    parameterValues = json.load(open(parameters_file_name, "r"))
    Parameters = collections.namedtuple( 'Parameters',
                    """
                    mpi_nodes
                    cluster_size
                    initial_cutoff
                    truncation_length
                    """
                    )
    parameters = Parameters(
        parameterValues.get(Parameters._fields[0].replace('_', '-'), 1),
        parameterValues.get(Parameters._fields[1].replace('_', '-')),
        parameterValues.get(Parameters._fields[2].replace('_', '-')),
        parameterValues.get(Parameters._fields[3].replace('_', '-'))
    )
    globals()["ControlParameters"] = parameters


#process the program argument(s)
err = ""

if len(sys.argv) != 2:
    raise Exception(
        """Usage:
                foo <control.json>
            Where:
                <control.json> is a dictionary of run parameters
        """
    )

# We expect a .json file with our parameters
parameters_file_name = sys.argv[1]
err += "" #validateFileArgument(parameters_file_name, exists=True)

if err == "":
    get_parameters(parameters_file_name)

    cp_dict = ControlParameters._asdict()
    for name in ControlParameters._fields:
        if cp_dict[name] == None:
            err += "Missing control parameter '%s'\r\n" % name

print err
print "Done"
1 голос
/ 31 декабря 2010

библиотека argparse хороша, она может обрабатывать большую часть анализа и проверки аргументов для вас, а также печатать красивые справочные экраны

[1] http://docs.python.org/dev/library/argparse.html

Я постучусьбыстрое демо, показывающее, как вы хотите использовать это arvo.

1 голос
/ 31 декабря 2010

Если у вас есть еще много параметров для обработки, может сработать что-то вроде этого:

def underscore(s):
  return s.replace('-','_')

# parameters with default values
for name, default in (("mpi-nodes", 1),):
  globals()[underscore(name)] = controls.get(name, default)

# mandatory parameters
for name in ("cluster-size", "initial-cutoff"):
  try:
    globals()[underscore(name)] = controls[name]
  except KeyError:
    err += "Missing control definition for %r" % name

Вместо манипулирования глобальными переменными вы также можете сделать это более явным:

def underscore(s):
  return s.replace('-','_')

settings = {}    
# parameters with default values
for name, default in (("mpi-nodes", 1),):
  settings[underscore(name)] = controls.get(name, default)

# mandatory parameters
for name in ("cluster-size", "initial-cutoff"):
  try:
    settings[underscore(name)] = controls[name]
  except KeyError:
    err += "Missing control definition for %r" % name

# print out err if necessary

mpi_nodes = settings['mpi_nodes']
cluster_size = settings['cluster_size']
initial_cutoff = settings['initial_cutoff']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...