2016-07-12 10 views
2

私は最後のpythonプロジェクトのためにしばらくしていましたので少し錆びています。何かアドバイスや批判を自由にお寄せください。 evalとJSONについてevalとjsonの変換と文字列のような辞書の解析

私はPython 2.6のデフォルトライブラリに限定されています。LDAP認証に使用される独自のLinuxベースのアプリケーションのデータベース内容を解析しようとしています。データベースを照会するために使用される特定のコマンドは、厳密には重要ではありませんが、私は含まれる出力返すために、次の方法を使用しています:

process = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE) 
stdout = process.communicate()[0] 

出力:

[{'header_obj_idx': 32, 
    'header_obj_state': 2, 
    'header_obj_type': 48, 
    'index': 2, 
    'name': '', 
    'obj_id': '8b14c165094d4cac81725227ce389277', 
    'ldap_data': '{"search_filter":"(sAMAccountName={username})","roles":["admin:CN=SuperUsers,DC=example,DC=com","read_only:CN=Users,DC=example,DC=com"],"search_base":"OU=Users,DC=example,DC=com","server_url":["ldap://ad.example.com","ldaps://ad.example.com:3001"],"user_to_dn_rule":"{username}@example.com","bind_dn":"CN=Bind,OU=Users,DC=example,DC=com","timeout":1500,"bind_pw":"xxxxxxxx","cache_expire":86400,"ca_cert_file":null}'}, 
{'header_obj_idx': 31, 
    'header_obj_state': 2, 
    'header_obj_type': 48, 
    'index': 1, 
    'name': '', 
    'obj_id': 'b0efc7a3d38a4f70abec4f73f69124de', 
    'ldap_data': '{"search_filter":"(sAMAccountName={username})","roles":["admin:CN=SuperUsers,DC=example,DC=com"],"search_base":"OU=Users,DC=example,DC=com","server_url":["ldap://169.254.0.1"],"user_to_dn_rule":null,"bind_dn":"CN=Bind,OU=Users,DC=example,DC=com","timeout":1500,"bind_pw":"xxxxxxxx","cache_expire":86400,"ca_cert_file":null}'}] 

を**私が出くわしましたshell=Trueには特定のセキュリティ上の影響があり、より良い解決策があるかどうか疑問に思っていましたか?私は成功し、個々の鍵ペアを解析することができましたが、私は私のマルチレベル変換は必要ありません感じて、より良い方法があるかもしれないと信じている?ast.literal_evaljson.loadsの両方を利用し

def ldap_data(stdout): 
    # evaluate object and return usable 'ldap_data' as dictionary 
    _data = ast.literal_eval(stdout)[0]['ldap_data'] 
    return json.loads(_data) 

ldap_data(stdout)['roles'] 

最後に、私はこのプロジェクトを始めたとき、それは、ユーザーが個々の展開がとても必要に応じて、複数のLDAPのconfigsを有することができることを私に起こったことはありません、、、私は実際に各辞書のインスタンスを解析に取り掛かる方法とは見なされません。私がこのソリューションで実行したロード・ブロックの数を考えると、誰かが上記のアウトプットで見つかった指標を利用したソリューションをエンジニアに助けてくれることを望んでいました。

謝罪していますので、私はこれをちょっと考えていきたいと思っています。改善するために何をするかを楽しみにしています。助けを前にありがとう! subprocessで単一のコマンドを実行するときにコマンド名と、各オプションの別々の文字列を作る場合

+0

私はこれがcodereview.stackexchange.comに適していると思っています。なぜなら、私はコード内に問題(バグ)が見えないからですが、改善のためのアイデアを探しているからです。 –

+0

出力はどのようになっていますか?正規のJSONの場合、literal_evalはまったく必要ありません。 'json'モジュールがそれを処理します。 – Keith

+1

@Keith残念ながら、ここで示されているのは有効なJSONではありません。上位レベルでは単純な引用符を使用し、キー 'ldap_data'の値はJSONを含む文字列として書式設定されています。私はそのような入力フォーマットでは、マルチレベルの変換を避けることはできないのではないかと心配しています。 –

答えて

2

一般的に、あなたはあなたがコマンドを実行する必要shell=Trueを行うすなわち、

['cmd', 'arg1', 'arg2'] 

shell=Trueを必要としないことthe docsに記載されているように、シェルの内部にあるか、他のシェルの機能を利用していますが、これは問題ではありません。

このデータの解析に関してはにはast.literal_evalが必要ですが、そのデータを有効なJSONにするには引用符を修正する必要があります。これは、既存の二重引用符をエスケープしてから、一重引用符を二重引用符に変換することで実行できます。修復されたデータがjson.loadsを使用してPythonリストに解析されると、json.loadsを再度呼び出してLDAP辞書を抽出する必要があります。

{ 
    "bind_dn": "CN=Bind,OU=Users,DC=example,DC=com", 
    "bind_pw": "xxxxxxxx", 
    "ca_cert_file": null, 
    "cache_expire": 86400, 
    "roles": [ 
     "admin:CN=SuperUsers,DC=example,DC=com", 
     "read_only:CN=Users,DC=example,DC=com" 
    ], 
    "search_base": "OU=Users,DC=example,DC=com", 
    "search_filter": "(sAMAccountName={username})", 
    "server_url": [ 
     "ldap://ad.example.com", 
     "ldaps://ad.example.com:3001" 
    ], 
    "timeout": 1500, 
    "user_to_dn_rule": "{username}@example.com" 
} 

{ 
    "bind_dn": "CN=Bind,OU=Users,DC=example,DC=com", 
    "bind_pw": "xxxxxxxx", 
    "ca_cert_file": null, 
    "cache_expire": 86400, 
    "roles": [ 
     "admin:CN=SuperUsers,DC=example,DC=com" 
    ], 
    "search_base": "OU=Users,DC=example,DC=com", 
    "search_filter": "(sAMAccountName={username})", 
    "server_url": [ 
     "ldap://169.254.0.1" 
    ], 
    "timeout": 1500, 
    "user_to_dn_rule": null 
} 

import json 

src = '''\ 
[{'header_obj_idx': 32, 
    'header_obj_state': 2, 
    'header_obj_type': 48, 
    'index': 2, 
    'name': '', 
    'obj_id': '8b14c165094d4cac81725227ce389277', 
    'ldap_data': '{"search_filter":"(sAMAccountName={username})","roles":["admin:CN=SuperUsers,DC=example,DC=com","read_only:CN=Users,DC=example,DC=com"],"search_base":"OU=Users,DC=example,DC=com","server_url":["ldap://ad.example.com","ldaps://ad.example.com:3001"],"user_to_dn_rule":"{username}@example.com","bind_dn":"CN=Bind,OU=Users,DC=example,DC=com","timeout":1500,"bind_pw":"xxxxxxxx","cache_expire":86400,"ca_cert_file":null}'}, 
{'header_obj_idx': 31, 
    'header_obj_state': 2, 
    'header_obj_type': 48, 
    'index': 1, 
    'name': '', 
    'obj_id': 'b0efc7a3d38a4f70abec4f73f69124de', 
    'ldap_data': '{"search_filter":"(sAMAccountName={username})","roles":["admin:CN=SuperUsers,DC=example,DC=com"],"search_base":"OU=Users,DC=example,DC=com","server_url":["ldap://169.254.0.1"],"user_to_dn_rule":null,"bind_dn":"CN=Bind,OU=Users,DC=example,DC=com","timeout":1500,"bind_pw":"xxxxxxxx","cache_expire":86400,"ca_cert_file":null}'}] 
''' 

#Escape existing double quotes, and then convert single quotes to double quotes 
data = json.loads(src.replace('"', '\\"').replace("'", '"')) 
for d in data: 
    ldap = json.loads(d['ldap_data']) 
    print json.dumps(ldap, indent=4, sort_keys=True), '\n' 

出力は、Python 2.6でテスト。6

ldap辞書のキー(および値文字列)はUnicode文字列であり、JSONダンプ内にnullと表された値は実際にはNoneであることに注意してください。

関連する問題