在JSON文件中处理Python程序参数

0 投票
4 回答
4654 浏览
提问于 2025-04-16 09:13

我刚开始学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 个回答

1

argparse库很不错,它可以帮你处理大部分的参数解析和验证工作,还能打印出漂亮的帮助信息。

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

我今天下午会快速做个演示,告诉你怎么使用它。

1

假设你有很多参数需要处理,像这样的方法可能会有效:

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']
2

通常,我们是这样做的。

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 )

最后,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'],
    )

我不知道你是否会觉得这样更好。

撰写回答