LINUX.ORG.RU

[python] Что заменяет source функцию bash

 


0

3

Вот опять та же проблема: пишу новый скрипт на Python и хочу считывать настройки (значения переменных) с файла. У bash делаю source <имя файла>, а как сделать у python?

Всегда обхожу эту проблему так: пишу баш срипт с source <Файл настроек>, а потом запускаю питон срипт с длинным перечнем параметров и разгребанием этих параметров уже в самом скрипте по переменным...


Ответ на: комментарий от baverman

И еще нельзя сделать import config-file. Внимание, дефис.

baverman ★★★
()

А если перечитать конфиг надо?

см. reload()

А если он не в sys.path?

Путь можно добавить в sys.path,

И еще нельзя сделать import config-file.

cм. __import__()

Вообще пиши нормальне конфиги, а не быдлокод в баш стиле. Есть куча способов записи конфига: ConfigParser, json. Или даже простой eval()

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

Только хотел написать про reload()...
В общем, всё верно. Импортируй и через reload() обновляй.

К слову, можно читать json-файл с настройками сразу вот так:
settings = eval(open(«config.json»))
Т.е. json это валидный питонокод(питонословари, точнее).

tia
()

Решено

Забыл сказать, у меня питон3

Считывание настроек с файла:

exec(open('/diskless/client/etc/client.conf',«rb»).read())

sdh
() автор топика
Ответ на: Решено от sdh

exec(open('/diskless/client/etc/client.conf',«rb»).read())

execfile('/diskless/client/etc/client.conf')

P.S. Лучше также еще передавать globals cловарь, чтоб текущие символы ненароком не потереть.

то есть:

conf = {}
execfile('/diskless/client/etc/client.conf', conf)
print conf['option']
baverman ★★★
()
Ответ на: Решено от sdh

у меня питон3

Тьфу, там же нет execfile.

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

см. reload()
Путь можно добавить в sys.path
cм. __import__()

Итого, вместо одной функции, которая для этого предназначена, мы получаем непонятную вундервафлю.

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

Итого, вместо одной функции, которая для этого предназначена, мы получаем непонятную вундервафлю.

Это было написано если очень хочется импортировать модуль. Как лучше и безопасно читать я уже написал ниже. Одной ф-ии здесь всё равно нет.

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

Это было написано если очень хочется импортировать модуль

Ну ТС то совсем не модуль хотел проимпортировать.

Одной ф-ии здесь всё равно нет.

Во втором питоне есть.

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

Кстати,

Как лучше и безопасно читать я уже написал ниже

И чем это лучше и безопаснее использовать контекстный менеджер?

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

Вы мне скажите еще аналог GNU bash read

там у него есть параметр -d <конец> тоесть читать до тех пор пока не встретится эта група символов...

вот мне бы чёто типа GNU-шного

read -d конец val

но на питоне.

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

И чем это лучше и безопаснее использовать контекстный менеджер?

Некоторые реализации питона без этого не сразу закроют файл (и нет гарантии что будущие версии CPython будут это делать). Контекстный менеджер гарантирует немедленное освобождение ресурса. Так просто правильнее делать.

Безопаснее использовать eval() вместо exec(), он накладывает немного больше ограничений на содержимое. Хотя оба варианта могут испортить выполнение.

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

аналог GNU bash read

Настолько высокоуровневой функции не знаю, но если файлы небольшие, то легче загонять всё содержимое в строку и далее split(), если делимитеры одинаковые или partition, если разные и нужно подобие конечного автомата.

Иначе полноценный read loop, с присущей ему аккуратностью на границах буфера.

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

и нет гарантии что будущие версии CPython будут это делать

Соглашусь.

Так просто правильнее делать.

Соглашусь. Но не всегда это необходимо.

Безопаснее использовать eval() вместо exec()

eval не может быть использован в контексте ТС.

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

надо читать с стандартного ввода

Если не нужно неблокирующего чтения, то вполне можно обойтись sys.stdin.read(BUFSIZE).

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

Извиняюсь, что пишу здесь, но что случилось со snaked? Неожиданно с 30 декабря напрочь прекратились коммиты (:

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

У меня только-только закончились праздники. Сегодня начну с новыми силами.

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

аналог GNU bash read

Настолько высокоуровневой функции не знаю, но если файлы небольшие, то легче загонять всё содержимое в строку и далее split(), если делимитеры одинаковые или partition, если разные и нужно подобие конечного автомата.

Иначе полноценный read loop, с присущей ему аккуратностью на границах буфера.

Не понял выше сказанное, сделал так:

GNU bash:

read -d END str_pckg

Аналог python:

def readinputstring(stop_symbols):
        stop_symbolslen=len(stop_symbols)
        stop_string=''
        for i in range(stop_symbolslen):
                stop_string=stop_string+'a';
        input_string=''
        while stop_string != stop_symbols:
                s = sys.stdin.read(1)
                stop_string = stop_string[1:stop_symbolslen]+s
                input_string=input_string+s
        return input_string


stop_symbols='END'
str_pckg = readinputstring(stop_symbols)
print (str_pckg)

Питон прога должна разгребать непрерывный поток (спец протокол) который создаёт nc от TCP/IP соединение и направляет в стандартный ввод. Может есть в питоне для этого более лучший инструмент чем написанний мной?

А если сам TCP/IP сервер на питоне писать... есть где готовые модули? Надо функционал примерно как:

socat TCP4-LISTEN:7777,fork,tcpwrap=client EXEC:/bin/Client-server.py,chroot=/diskless/client,su-d=client
sdh
() автор топика
Ответ на: комментарий от g1itch

Сначала напишу черновик на socat, а потом уж буду переписывать всё на питоне. А стоит всё писать на питоне?

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

IMHO стоит. А то опять получится монстр имеющий тонну зависимостей, без которых можно «легко» обойтись.

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

А если сам TCP/IP сервер на питоне писать... есть где готовые модули?

Если не хочется тянуть зависимости и сделать дешево и сердито, то помогут пакеты asyncore/asynchat из стандартной библиотеки.

Хотя конструкция с socat, в принципе, вполне летающая, пока не надо сложной логики обработки ошибок транспортного уровня.

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

Да к стати о зависимостях

У меня пока с сторонних зависимостей необходимы http://python.projects.postgresql.org/
и socat :)

Как в питоне на счёт зависимостей от сторонних модулей, модули иногда бросают?
Переписывают своевременно модули на новые версии питона?
Вот тот же Twisted пока не имеет версии под 3.0.
О используемом мной zope, plone - вообще смирился что надо держать 2.4. Но здесь весь комплекс на 2.4...

А как использовать в проге на 3.0 функционал модуля который работает в 2.7? Есть такая фича?

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

И по коду. Буфер в символ это конечно просто, но достаточно сильно просаживает по производительности, лучше как-то так:

import sys

BUF_SIZE = 1024

def read_until(ins, stop_seq, head=''):
    stop_seq_len = len(stop_seq)
    data = head
    pos = 0
    while True:
        if not head:
            buf = ins.read(BUF_SIZE)
            if not buf:
                return None, data

            data += buf

        pos = data.find(stop_seq, pos)
        if pos >= 0:
            return data[:pos], data[pos+stop_seq_len:]

        pos = max(len(data) - stop_seq_len, 0)
        head = None

head = ''
while True:
    data, head = read_until(sys.stdin, 'END', head)
    if not data:
        break

    print "[%s]" % data
baverman ★★★
()
Ответ на: комментарий от sdh

Как в питоне на счёт зависимостей от сторонних модулей, модули иногда бросают?

А как же. Три четверти, если не больше, PyPI это одноразовые наколенные поделия, выброшенные авторами на произвол.

Переписывают своевременно модули на новые версии питона?

А как использовать в проге на 3.0 функционал модуля который работает в 2.7? Есть такая фича?

Ну тут только один большой водораздел py2/py3, с последним пока не работал, поэтому ничего дельного сказать не могу.

Вот тот же Twisted пока не имеет версии под 3.0.

ИМХО, twisted перегруженный ненужный монстр, всегда можно обойтись другими средствами, без его привлечения.

О используемом мной zope, plone

Не повезло, сочувствую. Вообще поразительно, как оно еще шевелится с такими жесткими требованиями к окружению.

baverman ★★★
()

Столько всего понаписали, а по делу - ничего. Зато по twisted и zope местные профессионалы пройтись успели, это да.

Все рекомендации про exec, execfile, eval, reload - типичные медвежьи услуги. В сухом остатке, общие подходы к хранению конфигурации таковы (там вариантов, конечно, куда больше, но пусть хоть так будет):

  • конфигурация в виде python-модуля. Это дает наибольшую гибкость, но исключает возможность «горячей смены» конфигурации. reload? I don't think so.
  • конфигурация в каком-то сериализационном формате (ini/ConfigParser, sqlite, json, yaml). Пишете функционал для загрузки конфигурации (хинт - его не надо делать для каждого проекта отдельно) и вызываете, когда надо. Все. Минус - возможные ограничения формата.

Для работы с сетью - используем twisted.

Про `read -d' - вы знаете, что такое «цикл», ведь правда?

И вообще, читайте туториалы.

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

Мда... если конфиг рукописный, то execfile или exec по строчкам. И то и то делается в свое пространство имен (словарь), откуда потом настройки и тянуться.

Если конфиг просто для сохранения настроек, то pickle однозначно.

Если про работу с сетью, то можно и на питон, гляньте http://a-iv.ru/pyart/mysocket-I.pdf

С import для конфигов ИМНО лучше не связываться, неск идеологически неверно;-))))

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

идеологически неверно

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

))))

А, так вы лиспер? Тогда все ясно.

И да, никаких exec, execfile и pickle, пожалуйста.

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

конфигурация в виде python-модуля. Это дает наибольшую гибкость

Где гибкость в таких моментах как обязательное лежание такого конфига в sys.path и ограничение имени конфига питоньим идентификатором?

Все рекомендации про exec, execfile типичные медвежьи услуги.

Очень интересно про них услышать подробнее в канве проблемы ТС.

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

> обязательное лежание такого конфига в sys.path

так-таки и обязательное? Если хотите, чтобы он был доступен и в etc (ну, или где там), сделайте симлинк.

ограничение имени конфига питоньим идентификатором


Я не верю, что это такая огромная проблема. Мне не приходилось сталкиваться с реальными проблемами, связанными с этим «ограничением». А вам?

Гибкость заключается в том, что если у вас конфигурация в виде python-модуля, то это исключает этап десериализации / интерпретации параметров и (что самое главное) их типов. Т.е. вы можете использовать реальные ссылки на объекты в конфигурационном файле, а не их строковые эквиваленты (допустим, 'my_package.my_module.my_method') и танцы с importlib. Также вы можете использовать логические конструкции python, там где это уместно (допустим, при переключении между development/staging/production конфигурацией). Тут, разумеется, главное - не переборщить.

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

допустим, 'my_package.my_module.my_method'

допустим, при переключении между development/staging/production конфигурацией

execfile это позволяет. То есть прелестей импорта заместо непосредственного исполнения — нет. Зато есть недостатки.

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

Мне нередко приходилось импортировать модуль с конфигурацией из разных мест. Так что, мне во всех местах теперь execfile использовать? Да и, потом, execfile каждый раз исполняет код, а import - только один раз (если этот модуль еще не был импортирован никогда, грубо говоря), что обычно (по крайней мере, для меня) является желаемым поведением.

Но, знаете, я вот подумал - а что я вам тут буду доказывать? Ну хотите вы делать неправильно и не слушаете аргументов - ну и делайте. Не думаю, что небо упадет на землю, если вы будете использовать какие-то там execfile / eval. Такие дела.

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

Минусы import при загрузке конфига:

1) непонятно откуда именно потяентся конфиг, и без танцев с бубном (манипуляций с sys.path) зафиксировать это не представляется возможным.

2) все параметры живут внутри модуля, это не самое удобное место - лучше слдоварь, класс, все что угодно... можно конечно модуль превратить в словарь скажем, но опять таки танцы с бубном.

3) безопасность - при exec легко обеспечивается, при импорте всякие спец решения, я честно говоря не очень представляю как оно работает...

4) Главное - нам надо загрузить конфиг. Конфиги обычно простые вещи делают, там куча полей каких то задать... ну структурированный конфиг... его типа пишет пользователь (ну это приципиально ПРОСТАЯ вещь, много проще чем написание прогпраммы). И НАФИГА ТУТ ВСЯ МОЩЬ ИМПОРТА, А ЕСЛИ ОНА И ПРАВДА НУЖНА ТО ЧТО ЭТО ЗА КОНФИГ???? Вы его случаем с модуем __init___ не попутали?;-)))))

Я не лиспер, я просто часто улыбаюсь.

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

А у меня и так все ок без всякого ConfigParsera.

А у Вас? Что, никак на ЛОРе не получается зарегистрироваться?;-))))

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

непонятно откуда именно потяентся конфиг, и без танцев с бубном (манипуляций с sys.path) зафиксировать это не представляется возможным

>>> import zope.interface.common.interfaces
>>> zope.interface.common.interfaces.__file__
'/usr/lib/python2.6/dist-packages/zope/interface/common/interfaces.pyc'

Думаю, тут комментарии излишни?

все параметры живут внутри модуля, это не самое удобное место - лучше слдоварь, класс, все что угодно... можно конечно модуль превратить в словарь скажем, но опять таки танцы с бубном

Чем отличается обращение к атрибутам объекта класса от обращения к атрибутам модуля? Ничем.

безопасность - при exec легко обеспечивается

Покажете, как?

при импорте всякие спец решения, я честно говоря не очень представляю как оно работает

Вот так

Конфиги обычно простые вещи делают

Я бы так не сказал. Достаточно посмотреть на реализацию настройки логирования из стандартной библиотеки (ту, которая на ini-файлах).

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

> Думаю, тут комментарии излишни?

Не излишни. А если у меня локально лежит папка zope..., и в домашней директории лежит zope, и еще где то лежит zope, и все они разные - чего будет? Блин, да даже в многопользовательском режиме иногда непоятно кто откуда модуль импортитрует, регулярно с этим ошибки исправляю, а Вы про конфиг...

Чем отличается обращение к атрибутам объекта класса от обращения к атрибутам модуля? Ничем.


А если мне нужно отформатировать фтроку по словарю с ппаараметрами из конфига? А если мне нужно вычислить некое выражени в пространстве имен параметров конфига? Модуль и экземпляр класса похожи, но местьами очень сильно отличаются.

безопасность - при exec легко обеспечивается

Покажете, как?


D, G = {}, {}
for l in config :
if 'import' in l : throw 'ALARM!!!'
exec( l, G, D )

напр так.

Я бы так не сказал. Достаточно посмотреть на реализацию настройки логирования из стандартной библиотеки (ту, которая на ini-файлах).


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

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

>А у меня и так все ок без всякого ConfigParsera.

Я его тоже раньше не воспринимал, а оказалась неплохая штука.

А у Вас? Что, никак на ЛОРе не получается зарегистрироваться?;-))))

А мы, уважаемый не-лиспер, уже года 4 тут сидим, и нам совершенно это не надо:)

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

>>непонятно откуда именно потяентся конфиг, и без танцев с бубном (манипуляций с sys.path) зафиксировать это не представляется возможным

Думаю, тут комментарии излишни?

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.