LINUX.ORG.RU

Посоветуйте API

 


0

2

Здравствуйте

Есть задачка: загрузить json-схемы из папки и сделать их доступными в других иодулях програмы

Накалякал нечто в стиле node.js. По ощущениям, и API и сам код модуля вышли какие-то неочень. И, я не в курсе, но наверное, с этим кодом что-нибудь не так в плане потокобезопасности? Раз есть глобальная переменная

Как бы вы реализовали API для этой задачки?

# API
# Где-нибудь в main.py
from json_schema import load_schemas
load_schemas(project_dir / 'json_schema')

# Позже, в других модулях
from json_schema import schema
schema['user']

 

# модуль json_schema.py
from pathlib import Path
from typing import Any, Dict, Union
from json import load

schema: Dict[str, Any] = {}

def load_schemas(schemas_dir: Union[Path, str]) -> None:
    for p in Path(schemas_dir).iterdir():
        if p.is_file():
            with p.open() as f:
                schema[p.stem] = load(f)

★★★★★

Последнее исправление: makoven (всего исправлений: 6)

Публичное апи сделал бы так

from json_schema import get_schema
user = get_schema('user')
А сама get_schema уже подгружала файл 'user.json' с диска или брала из словаря schema, если к нему уже обращались и он подгружен.

Yur4eg ★★
()
Ответ на: комментарий от makoven

Я для таких задач использую синглетон с именем Environment, который подгружается из своего конфигурационного файла и уже дергается модулями.

Yur4eg ★★
()
Ответ на: комментарий от makoven

А в чем проблема указывать «project_dir / 'json_schema'» в json_schema (ну, точнее в get_schema, ну или там по импорту этому продумать нормально)? Плюс ты можешь там это указать как значение переменной, и если надо менять то после импорта пишешь что-то вроде «get_schema.SCHEMAS_PATH = '/foo/bar/1234/'».

micronekodesu ★★★
()

из def load_schemas лучше класс сделать, чтобы сократить «лесенку». Да и if p.is_file(): можно заменить на if not p.is_file(): continue

Ну а глобальная переменная зло ( учитывая что ты ее неправильно используешь -надо бы обьявить global внутри функции ). Лучше отдавать выходным аргументом функции. Да и вообще непонятна причина объявления schem снаружи функции в этом случае.

Jopich1
()
Последнее исправление: Jopich1 (всего исправлений: 3)
Ответ на: комментарий от Jopich1

учитывая что ты ее неправильно используешь - надо бы обьявить global внутри функции

Можно и объявить. Но в данном случае никакие линтеры не ругаются (ругаются только если присваивать к самой переменной, без квадратных скобочек)

Да и вообще непонятна причина объявления schem снаружи функции в этом случае

Для прикола) Указываешь тип переменной, и vscode сразу начинает относиться к ней с уважением, правильное автодополнение выдавать. Подчеркивать, если используешь ее неправильно

Лучше отдавать выходным аргументом функции

Кого куда отдавать?

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven
# API
# Где-нибудь в main.py
from json_schema import load_schemas
schema = load_schemas()

# Позже, в других модулях
from main import schema
schema['user']
# модуль json_schema.py
from pathlib import Path
from json import load


def load_schemas():
    schemas_dir = project_dir / 'json_schema'
    schema = {}
    for p in Path(schemas_dir).iterdir():
        if not p.is_file(): continue
        with p.open() as f:
            schema[p.stem] = load(p)
     return schema
Jopich1
()
Ответ на: комментарий от makoven

./json_schema/load_schemas.py

import os
import json

SCHEMA_DIR='/tmp/json_schema/'

def load(json_files_dir=SCHEMA_DIR):
    for root, dirs, files in os.walk(json_files_dir):  
        for filename in files:
            with open(filename) <... ну и вот это все с чтением json ...>

main.py

from json_schema import load_schemas

# Получаем данные из файлов в дефолтном /tmp/json_schema/
data = load_schemas.load()

# Получаем данные из файлов в каталоге /foo/bar/1234/
data = load_schemas.load('/foo/bar/1234/')

# А теперь тот же каталог /foo/bar/1234/, только меняем дефолтное значение
load_schemas.SCHEMA_DIR='/foo/bar/1234/'
data = load_schemas.load()

micronekodesu ★★★
()
Последнее исправление: micronekodesu (всего исправлений: 2)
Ответ на: комментарий от Jopich1

Конфиг есть. В общем, решил не разводить больше модулей с внутренним стейтом, а тупо загрузить схемы в конфиг, который уже импортировать в другие модули

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven

Твоя «глобальная переменная» это переменная модуля, если ты его импортируешь. Второе - каждый раз как ты импортируешь модуль, создаётся новый объект типа «модуль» со своими собственными переменными, не зависящими от других импортов.

# Позже, в других модулях
from json_schema import schema
schema['user']

schema всегда будет пустым словарём.

Я не понял, как ты собрался передавать данные «между модулями»?

anonymous
()
Ответ на: комментарий от makoven

А, всё. Я-то думал что это я чего-то не понимаю, но оказалось, что это у тебя проблемы с выражением мыслей.

anonymous
()
Ответ на: комментарий от anonymous

каждый раз как ты импортируешь модуль, создаётся новый объект типа «модуль» со своими собственными переменными, не зависящими от других импортов.

user@home:~$ cat one.py
NO_U = {}

user@home:~$ cat two.py
from one import NO_U
print(NO_U)

user@home:~$ cat main.py 
from one import NO_U
NO_U['Нет ты'] = 'Не понимаешь'
import two

user@home:~$ python3 main.py 
{'Нет ты': 'Не понимаешь'}
makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 2)
Ответ на: комментарий от Jopich1

В ноде они тоже давно существуют

В конце концов сделал так:

from pathlib import Path
from typing import Any, Dict, Union
from json import load

def load_schemas(schemas_dir: Union[Path, str]) -> Dict[str, Any]:
    schema = {}
    for p in Path(schemas_dir).iterdir():
        if not p.is_file(): continue
        with p.open() as f:
            schema[p.stem] = load(f)
        
    return schema

 

# config.py
from typing import Dict, Any
from pathlib import Path

from json_schema import load_schemas

project_path = Path(__file__).parent
json_schema_path = project_path / 'json_schema'

schemas: Dict[str, Any]

def _init():
    global schemas
    schemas = load_schemas(json_schema_path)

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.