Интерпретатор Python cmd, добавляющий инструкции if

#python #sql #control-flow

#python #sql #поток управления

Вопрос:

Для одного из моих проектов у меня есть программа на Python, построенная вокруг класса python cmd. Это позволило мне создать мини-язык вокруг инструкций sql, которые я отправлял в базу данных. Помимо того, что я значительно упростил подключение к python, я мог бы делать то, чего не может sql. Это было очень важно для нескольких проектов. Однако теперь мне нужно добавить блоки if для большего потока управления.

В настоящее время я думаю, что я просто добавлю в язык две новые команды, IF и END. Они устанавливают переменную, которая определяет, пропускать строку или нет. Я хотел бы знать, делал ли кто-нибудь еще это с помощью модуля cmd, и если да, существует ли стандартный метод, которого мне не хватает? Google, похоже, ничего не раскрывает, и документы cmd тоже ничего не раскрывают.

Идею, похожую на то, что я делаю, можно найти здесь. Вопросы и комментарии приветствуются. 🙂

Хм, немного сложнее, чем я думал, хотя синтаксис python был бы хорош. Я довольно долго обсуждал создание мини-языка, прежде чем, наконец, сделал это. Проблема в первую очередь возникает из-за внешних ограничений. У меня есть куча «данных», которые щедро преобразуются в sql. Это основано на других «данных», которые не будут проходить. Это также уникально для каждой конкретной «версии» проблемы. Моей первой склонностью было бы передавать прямые данные в sql, но это было непрактично.

Для любопытных я потратил много времени на изучение главы mini languages в the art of unix programming, которую можно найти здесь.

Если бы я создавал эту штуку на чистом python, у меня не было бы гибкости, которая мне абсолютно необходима для решения поставленной задачи.

Комментарии:

1. «У меня не было бы гибкости, которая мне была абсолютно необходима для решения поставленной задачи». Это не может быть правдой. Ваш DSL имеет меньше возможностей, чем Python, и теперь вам требуются дополнительные функции. У вас все еще нет языка Turing Complete в вашем DSL, поэтому вы жертвуете гибкостью. Кроме того, если вы перестроите его на чистый Python, вы ничем не пожертвуете. И вы получаете лучший синтаксис.

2. Я забыл упомянуть об этом там, но одно из основных ограничений заключается в том, что я должен вставлять данные в базу данных, затем на основе данных я выхожу, принимаю некоторые решения и вставляю еще некоторые данные, основываясь на данных, которые я получил. Мини-язык в основном представляет собой просто оболочку python для базы данных, обрабатывающую каждую часть функциональности как атомарную единицу. Я бы реализовал это как просто функции, но мне нужно было смешивать и сопоставлять их на основе сегодняшней проблемы, включить интерактивный режим, выполнить некоторую предварительную обработку и перенести это из другой программы.

3. @Spencer Rathbun: Ничего не меняется при переключении с cmd на правильный Python. Ничего не потеряно. Ни одна функция не потеряна. Функциональность не теряется. Изменяется только синтаксис.

4. Конечно, нет, дело не в этом. Правильный python — это не sql. Я не хотел находиться в командной строке и вводить:

5. Проклятая кнопка ввода. В целом: Конечно, нет, дело не в этом. За кулисами это python. Смысл мини-языка состоял в том, чтобы дать мне legos, а не atoms для выполнения чего-то совершенно другого. Теперь я оказался в ситуации, когда мне нужен новый конструктор lego. Итак, я хотел посмотреть, есть ли у кого-нибудь еще лучшая конфигурация атомов, чем та, что я придумал. Мне не нужен и, в частности, не нужен полномасштабный поток управления. Ваше решение заставляет меня отойти от парадигмы «водитель в машине с элементами управления» к человеку, нависающему над двигателем, крутящему карбюратор.

Ответ №1:

Ограничения создания «мини-языка» стали очевидными.

Соответствующие языки имеют древовидную структуру и более сложный синтаксис, чем cmd может быть легко обработан.

Иногда на самом деле проще использовать Python напрямую, чем изобретать свой собственный DSL.

В настоящее время ваш DSL, вероятно, считывает файл команд, подобный скрипту.

Из-за того, как cmd это работает, ваши маленькие комментарии получают строковый аргумент, который необходимо проанализировать. Затем команда выполняется. И, далее, каждая команда является методом cmd.Cmd подкласса.

Вот что вы можете сделать.

Каждый do_foo( self, args ) метод становится автономным вызываемым объектом. Он будет следовать шаблону проектирования команды. Он будет делать именно то, что сейчас делает функция метода. Не меньше. Точно то же самое.

 class Foo( object ):
    def __init__( self, global_context ):
        self.context= global_context
    def __call__( self, args ):
        ... The rest of do_foo ... 
  

Кроме того, ваш существующий cmd.Cmd подкласс, вероятно, поддерживает некоторое внутреннее состояние.
Все переменные self.this и self.that экземпляра должны быть изменены на reference
и явный объект контекста.

 class Context( object ): pass
  

Измените self.this or self.that на self.context.this or self.context.that

Теперь вы можете создать свой контекст и различные команды.

 ctx = Context()
foo= Foo(ctx)
  

Ваш скрипт немного изменяет синтаксис. От:

 foo argstring
bar argstring
  

Для:

 from mylanguage import foo, bar
foo( "argstring" )
bar( "argstring" )
  

Это делает именно то, что CLI делает сейчас. Больше ничего. Не меньше. Точно то же самое. Немного другой синтаксис.

Теперь ваш скрипт больше не находится в DSL, который сложно развернуть. Это на Python.

Сделав это, теперь вы можете использовать инструкции синтаксиса Python if .

У вас есть точная функциональность, реализованная в настоящее время в cmd , с улучшенным синтаксисом.

Ответ №2:

После еще одного изучения набора проблем я пришел к выводу, что могу оставить миниязык в покое. В нем есть все функции, которые мне нужны, и у меня нет времени перестраивать проект с нуля. Это была интересная проблема, и я больше не уверен, что создал бы другой миниязык, если бы столкнулся с такой же ситуацией. OTOH, здесь это работает очень хорошо, и я не хочу отказываться от преимуществ, которые это дало.