2010-12-30 5 views
0

저는 파이썬 초보자입니다. json 형식의 파일에있는 프로그램 매개 변수를 처리하는 것에 대한 조언을 원합니다. 현재, 나는 아래에 보여지는 것과 같은 것을하고있다. 그러나 그것은 너무 어리석은 것처럼 보이고, 동일한 리터럴 문자열을 여러 번 (때로는 대시와 밑줄을 사용하여) 타이핑하는 생각은 청소년 오류가있는 것처럼 보인다. -) (더 많은 매개 변수가 있습니다!)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 파일을 사용하고 하이픈이 연결된 매개 변수 이름을 사용하는 데 필요한 요구 사항이 있습니다. 어떤 아이디어?

정적 바인딩이 더 필요합니다. 아마 이것은 그것이 얻는만큼 좋다.

+0

무엇이 문제입니까? "뚱뚱한"이 무슨 뜻이야? 어떻게하면 좋을지에 대한 예를 들어 줄 수 있습니까? –

+0

Slott, 그냥 말투로 보인다. 그리고 (실제적으로) 똑같은 문자열을 여러 번 입력하는 전체 아이디어는 청소년처럼 보입니다 - 오류가 발생하기 쉽습니다 ... ----- 나는 더 많은 매개 변수를 가지고 있습니다! –

+1

의견이 아닌 질문의 입장을 설명해주십시오. ** 당신이 싫어하는 것을 밝히기 위해 질문을 ** 업데이트하십시오. –

답변

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

의 값을 가지고, 당신은이 작업을 수행. 당신이 namedtuple를 원하는 경우 mpi_nodes = params['mpi_nodes']

, 당신이 더 나은 여부를 찾을 줄 경우 나도 몰라이

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

같은 get_parameters을 변경합니다. 당신이 처리 할 더 많은 매개 변수가 가정

+0

나는 첫 번째 방법을 좋아한다. 사전을 사용하지 않고 사전의 "누락 된 키"동작을 사용합니다 (내가 한 것처럼). 전에 namedtuple 함수를 보지 못했습니다. 그래서 그것은 계시입니다! –

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'] 
+0

그게 좋습니다! 그것이 제공하는 기능을 사용하지 않을 경우 스크립팅 언어를 사용하는 것의 가치는 무엇입니까?하지만 그것은 말하기를 내 두뇌에 "GLOBALS? GLOBALS를 사용하고 있습니까?"라고 외치는 목소리가 있습니다. 사람 "B"가 따라 와서 내 코드를 살펴보기 시작하면 어떻게 이러한 변수가 무엇인지, 어디서 어떻게 알 수 있습니까? Get_Parameters 함수를 살펴 봐야할지 모르겠다면 그들은 허공에서 벗어난 것처럼 보입니다. 이 문제를 다루기위한 관습이나 관용구가 있습니까? 감사! David –

+0

@anyoneis : 조금 더 반복적 인 대가로 명시 적 변수 할당을 할 수도 있습니다. 내 편집을 참조하십시오. –

1

argparse 라이브러리입니다 좋은, 그것은 당신을 위해 인자 파싱과 유효성 검사의 대부분을 처리 할 수 ​​있고 예쁜 도움말 화면을 인쇄 할 수있다.

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

나는이 arvo를 어떻게 사용하고 싶은지 보여주는 간단한 데모를 작성합니다.

+0

고마워요! 나는 그 링크를 다른 날 사용 하겠지만 클라이언트는 .json 파일의 인자를 통해 프로그램을 제어하기를 원합니다. –

+0

'parse_args ("".join (controls))'내가 생각하는 트릭을해야합니다. – richo

1

나는이 모든 반응으로부터 무엇인가를 배웠다 - 고마워! 나는 각 제안에서 뭔가를 통합 접근 방식에 대한 피드백을 얻고 싶습니다.

1) 그 사용과 2를 디버깅하는 데 매우 분명하다)을 유지하고 수정하기 쉬운

내가 str.replace을 통합하기로 결정 : 클라이언트에 의해 부과 된 조건에 추가하여, 내가 뭔가를 원하는 , namedtuple 및 globals()를 호출하여 globals() 네임 스페이스에 ControlParameters 명명 된 튜플을 만듭니다.

#!/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"