LINUX.ORG.RU

Python, conditional compilation


0

1

Если честно, то долбаный питон. :)
Нужно сделать 2-3 независимый код.

if sys.hexversion >= 0x03000000: 
    тут что-то для 3 питона
else:
    тут для второго
Но, коряво это. И в случае когда зависит само определение класса, у меня вообще ступор.
Для 3 питона это будет так:
class MyClass(metaclass=MyMetaClass):
    ....

Для 2 питона это будет так:
class MyClass(object):
    __metaclass__=MyMetaClass
    ....
Вот что бы тут придумать? Как вариант, MyClass=MyMetaClass('MyClass', (object,), {}), но тут косяк если MyClass это парент класс. Может есть у кого мысли?

★★

Может,

if python3:
    from python3code import myclass
else:
    from python2code import myclass

?

tailgunner ★★★★★
()

1. Выносишь зависимый от версии код в отдельные модули, импортируешь один или другой в зависимости от. 2. Пишешь для 2х, используешь их 2to3 для генерации сорцов для третьей версии. И распространяешь либо обе по-отдельности, либо пишешь обертку, которая запускает одну или другую версию.

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

Не хочется делать дублирующийся код.
Отличие в данном случае только в части определения метакласса.

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

Млин, сколько копаюсь, то придется. :(
А как бы было замечательно.

#ifdef PY3
class MyClass(metaclass=MyMetaClass):
#elif
class MyClass(object):
    __metaclass__=MyMetaClass
#endif
    ....

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

Тебе уже шиза указал, как быть? Чо не нравится-то? Питон сам себе препроцессор.

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

Да, я уже задумался об этом варианте. :)

zJes ★★
() автор топика

Гых... а чего,

class myclass :
   if py3 :
       code for py 3
   else :
       code for py2

не устраивает? По секрету - тушка класса ничем не отличается от обычного кода, кроме пространства имен в котором это все раскручивается В частности, можно использовать exec, напр

if py3 : code1 = 'def hello( self ) : print("hello")'
else : code1 = 'def hello( self ) : print "hello"'
...
class C:
    exec( code1 )

Вообще я б вынес все специфичное в отдельные функции, определял бы их в зависимости от версии а дальше б юзал.

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

тушка класса ничем не отличается от обычного кода

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

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

Сорри, неск туплю, сразу не просек проблему... Но все равно есть много решений в рамках самого питона, например написать файл-шаблон, который форматировать по словарю в зависимости от версии и ехес-ать (импортировать), это будет куда гибче С-шного препроцессора.

Можно попытаться устроить читерство со стеком. Можно попытаться разобраться с устройством классов в пит3 - ИМНО таки можно подкрутить чсе что нужно и после заголовка класса, но не уверен, на 3м ни писал. Вообще все больше убеждаюсь что 3й питон это большая ошибка... НЕЛЬЗЯ НИКОГДА ТЕРЯТЬ ОБРАТНУЮ СОВМЕСТИМОСТЬ!

А вообще нафига наследование от object? Скока пишу, так и не понял;-))))))))))

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

В общем да... тогда форматирование файла (построчное) по словарю - будет тот же препроцессор. Причем можно делать так:

%(PY3)sclass A(metaclass=B) :
%(PY2)sclass A(object) :
...

а в словаре {'PY2':", 'PY3':'#'} или наборот, и вся любовь.

Можно в качестве словаря сувать свой класс его эмулирующий и использовать уже всякие хитрые ключи, типа %(object:metaclss=B)s

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

Вообще все больше убеждаюсь что 3й питон это большая ошибка... НЕЛЬЗЯ НИКОГДА ТЕРЯТЬ ОБРАТНУЮ СОВМЕСТИМОСТЬ!

таким путём уже пробовали - java получается, как минимум стоило попытаться

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

Поясни? :)

Ну делать 2 на 90% одинаковых кода, не комильфо, хочется же или в рантайме, в крайнем случае через кодогенератор, во втором-то случае все ок.

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

> Ну делать 2 на 90% одинаковых кода, не комильфо

Ну да, а тащить с собой препроцессор/кодогенератор (или делать свой) - это комильфо? И ради чего - чтобы не дублировать 2 строки кода?

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

Ну простой пример,

class A(metaclass=AMeta):
    prop1 = 10
    prop2 = 11
    prop3 = 12
    prop4 = 13
    prop5 = 14
    ....
Думаешь, что иметь 2 таких класса с отличием в 1 строчку комильфо?

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

У меня, конечно, пока нет опыта в поддержке кода для двух версий, но snaked для python3 я планирую вести в отдельном бранче. Не думаю, что конфликтов будет много. Это принципиально, чтоб один пакет работал на всех питонах?

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

2 класса против кодогенерации в рантайме - я выбираю 2 класса.

Это не говоря уже о том, что A.prop* можно присваивать в коде, общем для обеих версий.

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

Желательно, надо просто за уши притянуть проект который по заданию сделан на 3 питоне, но в реальности еще должен работать на 2 питоне. Бренч это выход, но сам понимаешь, суппортить 2 кода, которые на 99% одинаковы немного неудобно. Либо переосмыслить некоторые вещи, такие как метаклассы.

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

> 2 класса против кодогенерации в рантайме - я выбираю 2 класса.
Если на этапе установки проекта, то лучше все-таки кодогенерация.

В общем хез. Буду думать, пока время есть.

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

>Бренч это выход, но сам понимаешь, суппортить 2 кода, которые на 99% одинаковы немного неудобно.

Делай одну ветку, для py3, а вторую получай кодогенерацией, прогоняя основной код через sed/awk/whatever. Можно в виде make-файла сделать, а можно чуть ли не при запуске проходить по исходникам. Эдакий py2to3 наоборот.

Естественно, это сработает только если у тебя нет существенных отличий в коде.

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

>Вообще все больше убеждаюсь что 3й питон это большая ошибка... НЕЛЬЗЯ НИКОГДА ТЕРЯТЬ ОБРАТНУЮ СОВМЕСТИМОСТЬ!

У них не было выбора. Надо было править недостатки языка. Иначе их просто не убрать.

А вообще нафига наследование от object? Скока пишу, так и не понял;-))))))))))

Были очень даже объективные причины, есть проблемы, которые вылазят при множественном наследовании. Вот тут всё нормально расписано:

http://www.python.org/download/releases/2.3/mro/

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

Ну я вчера вечером примерно подобное и потренировался, #ifdef #endif и configure.py который, в зависимости от питона под которым был запущен, генерит ветки. Склоняюсь все-таки к этой версии, к примеру, для PyQt отличия в ген.файлах, то есть надо перегенерировать еще и ui и qrc файлы, простым рантаймом думаю не обойдешься.

zJes ★★
() автор топика

Да вы ударились тут все.

Все нормальные люди либо пишут на Питоне-2 и используют 2to3.

Либо пишут на Питоне-3 и используют 3to2.

На эту тему есть ТЫЩА разных факов, блогов и статей, где всё разжёвано.

Хотя лично ОПу я ничего советовать не буду, он, похоже, просто пообщаться пришёл.

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

>Ну я вчера вечером примерно подобное и потренировался, #ifdef #endif и configure.py который, в зависимости от питона под которым был запущен, генерит ветки.

Имхо не стоит портить код проекта на py3 какими-то мутными ifdef-ами. Лучше всё делать сторонними регэкспами.

И, наверное, лучше не пытаться сделать монстра, определяющего питоновские версии, а просто сделать мейкфайл с командами make py3 и make py2.

В этом случае будет чистый и правильный py3 код и такой же чистый и правильный py2 код, генерящийся по желанию.

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

2to3 в большинстве случаев на г.

Пример, for key in dict.keys() от тупо сделает for key in list(dict.keys()) хотя это нахрен не надо.

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

Ну просто попробовал на тестах. :)
Не монстр там, там был по сути перебор файлов, регэкспы и тестовая компиляция файлов.

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

Потому что ты трогаешь себя ночью.

Открой для себя for key in dict.

Если шибко умный, используй iterkeys/iteritems/itervalues.

А теперь вали отсюда читать маны, либо попроси маму, если сам не умеешь.

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

Это был пример... для твоего понимания.

Или ты думаешь что 2to3 DictMixin в MutableMapping сам что ли переделает? Ошибаешься.

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

Чел, ты не выспался? Или ты полагаешь, что программы пишет 1 человек и , к примеру, мне нужно переписать логику за другими что-бы потом запустив 2to3 всем стало хорошо?

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

Чел, ты не выспался? Или ты полагаешь, что программы пишет 1 человек и , к примеру, мне нужно переписать логику за другими что-бы потом запустив 2to3 всем стало хорошо?

если так рассуждать то надо сразу себя зарыть об стену и не жить

//для кого code review и статические анализаторы кода понапридумывали?

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

Ох щи.
Неэфимерный пример, есть рабочий и используемый проект на 2 питоне, разрабатывается несколькими людьми, есть ты, которому нужно сделать бранч на 3 питон. Ты полезешь менять рабочий оттестированный код только из-за того, что бы корректно отработал скрипт? Я тот py2to3 использую только для просмотра и патча очевидных и простых изменений, не полагаясь полностью на него. И что, орать сразу про дверь?

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

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

за корректность и «оттестированность» кода у меня обычно отвечают тесты, не вижу почему бы не натравить их на проект ещё раз, с целью отслеживания регрессий (ведь задача ставится - надо сделать, а не «хорошо бы посмотреть - а ну как 3-й питон будет получше»)

только из-за того, что бы корректно отработал скрипт?

какой скрипт?

И что, орать сразу про дверь?

я про дверь не орал :) просто всегда в команде находятся блохастые программисты и их всё равно приходится причёсывать и проводить с ними профилактику

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

> у меня обычно отвечают тесты
Это правильно, но в некоторых случаях тесты тоже надо с 2 на 3 переводить. :)

какой скрипт?

Выше меня тыкали носом в py2to3.

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

> у меня обычно отвечают тесты Это правильно, но в некоторых случаях тесты тоже надо с 2 на 3 переводить. :)

вот и, работая согласно принципу TDD, сначала правишь код теста - он не срабатывает, дальше делаешь чтобы он срабатывал и рефакторишь :)

> какой скрипт?

Выше меня тыкали носом в py2to3.

ну, если для дела нужно - пуркуа бы и не па тогда, имхо гораздо более страшные делом является поддерживание 2-х веток кода в актуальном состоянии

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

> вот и, работая согласно принципу TDD, сначала правишь код теста - он не срабатывает, дальше делаешь чтобы он срабатывал и рефакторишь :)
Как ты представляешь сделать перевод тестов на 3, не сделав предварительного перевода проекта, хотя бы что-бы не валилось все с синтаксическими ошибками? 100% fault я и без этого увижу. :)

имхо гораздо более страшные делом является поддерживание 2-х веток кода в актуальном состоянии

Эм, ну да ладно. Как раз с этого тема и началась. ;) Но рассчитывать только на py2to3 я бы не стал... из-за обширного наступления на грабли.

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

> вот и, работая согласно принципу TDD, сначала правишь код теста - он не срабатывает, дальше делаешь чтобы он срабатывал и рефакторишь :)

Как ты представляешь сделать перевод тестов на 3, не сделав предварительного перевода проекта, хотя бы что-бы не валилось все с синтаксическими ошибками? 100% fault я и без этого увижу. :)

так TDD же, и должно отваливаться, потихоньку напильничком до самолёта обтачиваешь, если mass-fail, «комментишь» и делаешь рефактор кусками, по одному

> имхо гораздо более страшные делом является поддерживание 2-х веток кода в актуальном состоянии

Эм, ну да ладно. Как раз с этого тема и началась. ;) Но рассчитывать только на py2to3 я бы не стал... из-за обширного наступления на грабли.

ну, на py2to3 свет клином не сошёлся, если уж так жмёт - пишем своё, лёгкое велосипедостроение ещё ни одного бобра не убило

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

>>Вообще все больше убеждаюсь что 3й питон это большая ошибка... НЕЛЬЗЯ НИКОГДА ТЕРЯТЬ ОБРАТНУЮ СОВМЕСТИМОСТЬ!

У них не было выбора. Надо было править недостатки языка. Иначе их просто не убрать.

Пссссс... так они поправили то, что не критично ни разу, а то что критично оставили. Где групповые комментарии, почему остались жить неизменяемые объекты (90% ошибок именно из за этого разделения), где нормальная многопотчность? Нафига терять обратную совместимость из за всякой фигни, и при этом оставлять самые серьезные дырки?

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

> Где групповые комментарии, почему остались жить неизменяемые объекты (90% ошибок именно из за этого разделения),

Штоето?

где нормальная многопотчность?

Она не требует несовместимых изменений в языке.

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

> почему остались жить неизменяемые объекты

Immutable? Что с ними не так?
Если честно мало что понял.

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

Групповые - описался, многострочные. Аналог /* */

Многопоточность не требует, но ее не хватает гораздо сильнее, чем print как ф-ии.

Про неизменяемые объекты - строки и числа в 2х неизменеямы. В 3х это разве поменялось? Если да, то я нигде про это ни слова не видел. А между тем, это убивает всю стройность питоновой концепции. Код a+=[1] для списка и a+=1 для числа даст совершенно разные результаты - список будет изменен, но вместо числа появится новое число (а все старые индентификаторы останутся неизменными).

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

Если да, то я нигде про это ни слова не видел. А между тем, это убивает всю стройность питоновой концепции. Код a+=[1] для списка и a+=1 для числа даст совершенно разные результаты - список будет изменен, но вместо числа появится новое число (а все старые индентификаторы останутся неизменными

А тебе какое поведение кажется нормальным?

И вообще, если вот такая штука приводит к куче проблем, из-за мутабельности дикт-ов, то что же будет при изменяемых чисел?

def function(a, b, c={}):
    ....
anonymous
()
Ответ на: комментарий от AIv

Групповые - описался, многострочные. Аналог /* */

да куда они делись? всегда-ж были :)

def foo():
    """
    this is the first comment line
    this is the second comment line
    """
    None

как то так

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

> Многопоточность не требует, но ее не хватает гораздо сильнее, чем print как ф-ии.

Это да, но... претензия нерелевантна.

Про неизменяемые объекты - строки и числа в 2х неизменеямы. В 3х это разве поменялось?

Нет, слава ТНБ.

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

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

Проблемы с тем, что ты не можешь поменять глобальную переменную из импортированного модуля если она число, но можешь поменять если она словарь, а еще можешь поменять локальную переменную висящую на замыкании ф-ии вне зависимости от того кто она - вот от этого башка и правда идет кругом. Ладно, я то ко всему уже привык, но у неподгтовленного пользователя такие вещи вызывают ступор.

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

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

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

>Я например люблю комментить неиспользуемые куски кода - чего мне их, в строку загонять???

Я не знаю как у вас, но у культурных людей редактор комментирует блок кода автоматом, если этот блок кода выделить, и, например, нажать M-;

:)

anonymous
()

Все проблемы от бездарности!
Классы генерятся в компайл-тайме, тогда и могут, конечно, быть проблемы.
Тебе же нужно делать это в рантайме. В рантайме то выполняется? Функции!

def gen_my_class():

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