3

Python を使用して JSON を作成したいと考えています。

役立つライブラリが見つからなかったので、Python ファイル内のクラスの順序を調べることができるかどうか知りたいですか?

# example.py
class Foo:
    pass

class Bar:
    pass

をインポートする場合example、クラスの順序を知りたいです。この場合、[Foo, Bar] であり、[Bar, Foo] ではありません。

これは可能ですか?「はい」の場合、どのように?

バックグラウンド

yaml/json に満足していません。Python クラス (オブジェクトへのインスタンス化ではなく、クラスのみ) を介して構成を作成するという漠然とした考えがあります。

私の目標 (簡単で楽しいツールで JSON を作成する) を達成するのに役立つ回答は大歓迎です。

4

8 に答える 8

3

まず、私が見ているように、あなたができることは2つあります...

  1. 構成ファイルとして Python ソース ファイルを使用することを引き続き追求します。(これはお勧めしません。ブルドーザーを使って釘を打ったり、散弾銃を車輪に変えたりするようなものです)
  2. ジョブ用に設計された構成ファイルをTOMLJSONまたはYAMLなどに切り替えます。

    JSON または YAML には、「順序付けられた」キーと値のペアを保持することを妨げるものは何もありません。Python のdictデータ型はデフォルトで順序付けされておらず (少なくとも 3.5 まで)、listデータ型は順序付けられています。これらは、デフォルトのローダーを使用する場合、それぞれ JSON のオブジェクトと配列に直接マップされます。OrderedDictそれらを逆シリアル化するときにPythonのようなものを使用するだけで、順序が保持されます!


それはさておき、構成に Python ソース ファイルを本当に使用したい場合は、astモジュールを使用してファイルを処理することをお勧めします。抽象構文ツリーは、構文レベルの分析のための強力なツールです。

ファイルからクラスの行番号と名前を抽出する簡単なスクリプトを作成しました。

あなた(または実際には誰でも)は、それを使用または拡張して、より広範囲に拡張し、必要に応じてより多くのチェックを行うことができます。

import sys
import ast
import json


class ClassNodeVisitor(ast.NodeVisitor):

    def __init__(self):
        super(ClassNodeVisitor, self).__init__()
        self.class_defs = []

    def visit(self, node):
        super(ClassNodeVisitor, self).visit(node)
        return self.class_defs

    def visit_ClassDef(self, node):
        self.class_defs.append(node)


def read_file(fpath):
    with open(fpath) as f:
        return f.read()


def get_classes_from_text(text):
    try:
        tree = ast.parse(text)
    except Exception as e:
        raise e

    class_extractor = ClassNodeVisitor()

    li = []
    for definition in class_extractor.visit(tree):
        li.append([definition.lineno, definition.name])

    return li


def main():
    fpath = "/tmp/input_file.py"

    try:
        text = read_file(fpath)
    except Exception as e:
        print("Could not load file due to " + repr(e))
        return 1

    print(json.dumps(get_classes_from_text(text), indent=4))


if __name__ == '__main__':
    sys.exit(main())

次のファイルでのサンプル実行を次に示します。

input_file.py:

class Foo:
    pass


class Bar:
    pass

出力:

$ py_to_json.py input_file.py
[
    [
        1,
        "Foo"
    ],
    [
        5,
        "Bar"
    ]
]

インポートexampleすると、

モジュールをインポートする場合、exampleモジュールはインポート パス上にあります。インポートとは、モジュール内の任意のPython コードを実行することを意味しexampleます。これはかなり大きなセキュリティ ホールです。アプリケーションの残りの部分と同じコンテキストで、ユーザーが編集可能なファイルを読み込んでいます。

于 2016-12-06T17:45:28.523 に答える
2

クラス定義の順序を維持することに関心があるため、各クラス内の定義の順序も維持することに関心があると思います。

python3.6 以降、これが python のデフォルトの動作になったことを指摘する価値があります。

PEP 520 : Preserving Class Attribute Definition Orderも参照してください。

于 2016-12-09T05:29:50.573 に答える
2

(コメントを回答に移動)

それは非常に漠然とした考えです。Figura試してみてください それはまさにそれを行います。

(完全開示: 私は Figura の作者です。)

宣言の順序は Figura では保持されておらず、json でも保持されていないことを指摘しておく必要があります。

YAML での順序保持についてはよくわかりませんが、wikipediaでこれを見つけました:

...仕様によると、マッピングキーには順序がありません

必須ではありませんが、特定の YAML パーサーが順序を維持している場合があります。

于 2016-12-05T20:03:39.963 に答える
1

標準のjsonモジュールは使いやすく、JSON 構成ファイルの読み取りと書き込みに適しています。

オブジェクトは JSON 構造内で順序付けされていませんが、リスト/配列では順序付けられているため、順序に依存する情報をリストに入れます。

私はクラスを構成ツールとして使用しました。私が行ったことは、特定のクラス変数によってカスタマイズされた基本クラスからクラスを派生させることでした。このようなクラスを使用することで、ファクトリ クラスは必要ありませんでした。例えば:

from .artifact import Application
class TempLogger(Application): partno='03459'; path='c:/apps/templog.exe'; flag=True
class GUIDisplay(Application): partno='03821'; path='c:/apps/displayer.exe'; flag=False

インストールスクリプトで

from .install import Installer
import app_configs

installer = Installer(apps=(TempLogger(), GUIDisplay()))
installer.baseline('1.4.3.3475')
print installer.versions()
print installer.bill_of_materials()

仕事には適切なツールを使用する必要があるため、注文が必要な場合、Python クラスは適切なツールではない可能性があります。

JSON ファイルの作成に使用したもう 1 つの Python ツールは、Makoテンプレート システムです。これは非常に強力です。これを使用して、IP アドレスなどの変数を静的 JSON ファイルに入力し、C++ プログラムで読み取りました。

于 2016-12-06T00:33:00.523 に答える
1

これがあなたの質問に答えているかどうかはわかりませんが、関連している可能性があります。優れたattrsモジュールを見てください。データ型として使用するクラスを作成するのに最適です。

glyph のブログ (Twisted Python の作成者)の例を次に示します。

import attr
@attr.s
class Point3D(object):
    x = attr.ib()
    y = attr.ib()
    z = attr.ib()

多くのボイラープレート コードを書く手間が省けます -str表現や比較などを無料で取得でき、モジュールにはライブラリasdictに渡すことができる便利な関数があります。json

>>> p = Point3D(1, 2, 3)
>>> str(p)
'Point3D(x=1, y=2, z=3)'
>>> p == Point3D(1, 2, 3)
True
>>> json.dumps(attr.asdict(p))
'{"y": 2, "x": 1, "z": 3}'

このモジュールは奇妙な命名規則を使用していますがattr.s、「attrs」およびattr.ib「attrib」と読めば問題ありません。

于 2016-12-09T05:06:20.013 に答える
0

PythonからJSONを作成するポイントに触れただけです。Pythonオブジェクトをjsonにダンプできるjsonpickleという優れたライブラリがあります。(これを単独で使用するか、ここに記載されている他の方法と組み合わせて使用​​すると、おそらく必要なものを取得できます)

于 2016-12-10T12:21:16.423 に答える