web-dev-qa-db-ja.com

pythonからjqを実行する方法はありますか

pythonスクリプトからjqコマンドを実行しようとしています。現在、ターミナル(MacO)から実行すると、jqコマンドは正常に動作しています。

cat filename.json |jq '{Name:.name, address:.address[0][1].street}'

基本的に私はjqを使用してJSONからデータを抽出しようとしています。 JSONにはネストされた配列が含まれているため、変数を使用してループする必要があります。

私の質問は-

  • このコマンドをpythonスクリプトから実行できますか?
  • それが可能であれば、ネストされた配列をどのようにループするか
  • 上記のサンプルデータの要素(address [] []。street)

互換性の問題が発生するため、Python以外の言語を使用したくありません。

10
FirstName

Jqから [〜#〜] faq [〜#〜]

Q:Pythonで使用できるバインディングは何ですか?

A:

pip install jq#詳細については、 https://pypi.python.org/pypi/jq を参照してください

pip install pyjq#詳細は、 https://pypi.python.org/pypi/pyjq を参照してください

ネストされた配列については、それをループすることは、jq内で実行できる(そしておそらく実行する必要がある)もののように聞こえます。

13
peak

pythonでC apiを使用する適切な方法はpythonバインディングライブラリ、およびその両方を経由するため、受け入れられた答えはピークの答えである必要があります- https://pypi.python.org/pypi/jq および https://pypi.python.org/pypi/pyjq は期待どおりに機能するはずです。


そうは言っても、私たちはpythonについて話しているので、私はもっとPythonicである代替をもたらしたいと思います:glompip install glomhttps://glom.readthedocs.io/

jqのようにDSLを使用する代わりに、glomでは、純粋なpythonを使用して、目的の形式で出力を宣言するだけです(この出力形式はspec)この場合、単純なdictが必要です。

spec = {'Name': 'name',
        'street': 'address.0.1.street'}

次に、データに対してglomを呼び出します。

output_data = glom(input_data, spec)

jqと同様に、コマンドラインでglomを使用することもできます。

cat filename.json | glom "{'Name': 'name', 'street': 'address.0.1.street'}"

完全なpythonの例:

import json
from pprint import pprint
from glom import glom


with open('filename.json', 'rt') as f:
    input_data = json.load(f)

spec = {'Name': 'name',
        'street': 'address.0.1.street'}

output_data = glom(input_data, spec)

pprint(output_data)
8
Fabiano

sh モジュールを使用すると、Pythonからjqサブプロセスを簡単に呼び出すことができます。例えば.

import sh
cmd = sh.jq('-M', '{Name:.name, address:.address[0][1].street}', 'filename.json')
print "cmd returned >>%s<<" % cmd.stdout
3
jq170727

まあ、私はjqの大ファンですが、Python=でも簡単に実行できないことをしているようには見えません。考慮してください。

import json

with open("filename.json", "r") as f:
    data = json.load(f)

{"Name": data["name"], "address": data["address"][0][1]["street"]}
3
user3899165
  1. このコマンドをpythonスクリプトから実行できますか?

はい、サブプロセスを使用します。例:

jsonFile = '/path/to/your/filename.json'
jq_cmd = "/bin/jq '{Name:.name, address:.address[0][1].street}' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, Shell=True)

# read JSON object, convert to string, store as a dictionary

jDict = json.loads(jq_proc.stdout.read())
jq_proc.stdout.close()
  1. それが可能である場合、上記のサンプルデータのネストされた配列要素に対してどのようにループするか(address [] []。street)

いくつかのレコードを含むJSONデータセットを表示すると役立ちます。 pythonのJSONセットをループする場合、オブジェクトの数を取得して反復するのは簡単です。わずかなオーバーヘッドですが、コードを理解しやすくします。

# count number of JSON records from the root level

jq_cmd = "/bin/jq '. | length' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, Shell=True)

jObjCount = int(jq_proc.stdout.read())
jq_proc.stdout.close()

# iterate over each root level JSON record

for ix in range(jObjCount):

  jq_cmd = "jq '. | .[" + str(ix) + "]' " + jsonFile 
  jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, Shell=True)

  # read object, convert to string, store as a python dictionary

  jDict = json.loads(jq_proc.stdout.read())

  # iterate over nested objects within a root level object    
  # as before, count number items but here for each root level JSON object

  jq_cmd = "/bin/jq '. | .[" + str(ix) + "].sub_Item_Key | length' " + jsonFile
  jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, Shell=True)
  jItemCount = int(jq_proc.stdout.read())
  jq_proc.stdout.close()

  for jx in range(jItemCount):

     jq_cmd = "/bin/jq '. | .[" + str(ix) + "].sub_Item_Key[" + str(jx) + "]' " + jsonFile
     jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, Shell=True)

     # read JSON item, convert to string, store as a python dictionary

     jItemDict = json.loads(jq_proc.stdout.read())

楽しい!

2
endurogizer