LINUX.ORG.RU

Организация небольшого проекта на Python

 


2

2

Запилил маленькую консольную утилиту для генерации заголовочных файлов с описанием регистров и прерываний (пример - http://pasted.co/31caec09), а также скрипта линковщика (а ещё выводит необходимые ключики компилятора). Полезно при программировании некоторых микроконтроллеров (в данный момент поддерживается лишь два семейства ARM).

Проект небольшой, но таки состоит из нескольких файлов. Хотел бы узнать как правильно его структурировать (или все py-файлы в корне это ок?). А также как облегчить его установку и опакечивание (в случае C/C++ проекта я бы добавил цели install/uninstall в Makefile).

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

Ссылка: https://github.com/KivApple/mcu-info-util

★★★★★

setuptools для установки. Файлы из корня можно перенести в поддиректорию, а в корне сделать скрипт для запуска.

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

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

Следует ли создавать в поддиректории файл __init__.py?

KivApple ★★★★★ ()

файлы в корне тоже ок - когда разростется перенесешь в ./mcu/ || ./src/mcu/

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

если ты пишешь библиотечный код - в этом есть смысл, как я понимаю твой проект сами бинари (то что обычно ложат в ./bin | ./scripts)

import mystuff


if __name__ == "__main__":
    mystuff.Application().run()

если будешь импортировать модули - следует

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

Перенёс всё в подкаталог mcu_info_util. Главный файл переименовал в __init__.py, весь код из него обернул в def main(argv). В корне же создал файл, который импортирует этот модуль и вызывает из него main, передавая в качестве аргумента sys.argv.

https://github.com/KivApple/mcu-info-util/blob/master/mcu-info-util.py

Правильно?

Что, кстати, делать с каталогом metadata? Там хранятся всякие вспомогательные данные (база микроконтроллеров), которые нужны программе во время работы. Её же можно будет как-нибудь поставить в систему с помощью setuptools? И как правильно потом внутри программы определять местоположение этого каталога (сейчас определяю относительно имени файла скрипта)?

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

надо прописать в setup параметр data_dir или что-то вроде, почитай. все это уже вопрос вкуса, делай как нравится

trashymichael ★★★ ()
Последнее исправление: trashymichael (всего исправлений: 1)
Ответ на: комментарий от KivApple

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

Первое что нашел в гугле https://chriswarrick.com/blog/2014/09/15/python-apps-the-right-way-entry_poin... Он тебе сам создаст файл где-нибудь в /usr/local/bin/<script_name> и будет импортировать твой модуль при запуске. Пакетные менеджеры умеют хендлить setup.py и почти автоматически генерировать пакет. Например, https://wiki.debian.org/Python/Pybuild так.

Следует ли создавать в поддиректории файл __init__.py?

Все что импоритируется в python должно иметь __init__.py. Он может быть пустой, не обязательно там описывать какую-то логику.

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

О. Отлично. Удалил самодельный скрипт и сделал по той инструкции. python setup.py install отлично ставит в систему мою программу и создаёт обёртку для запуска. Осталось разобраться, как установить в систему не только исполняемые файлы, но файлы данных.

KivApple ★★★★★ ()

Интересный вопрос. По-моему, «правильно структурировать» это вопрос некроссплатформенный, по крайней мере, в треде все советы Linux only.

А что никто не советует pypi.python.org? С установкой pip install <package>?

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

Интересный вопрос. По-моему, «правильно структурировать» это вопрос некроссплатформенный, по крайней мере, в треде все советы Linux only.

www.linux.org.ru нет?

А что никто не советует pypi.python.org? С установкой pip install <package>?

Потому что pypi это сторадж и там кастомного пакета не будет до тех пор, пока автор его туда не зальет.

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

Уже сделал следующим образом:

setup(
	...
	data_files=[
		(d, [os.path.join(d, f) for f in files]) for d, folders, files in os.walk('share')
	]
)

Теперь проблема в том, как к этим файлам обращаться из своей программы. Сейчас они попадают в /usr/share/mcu-info-util (часть пути share/mcu-info-util я задал сам, создав соответствующую структуру, ибо негоже мусорить прямо в /usr). Однако префикс установки может отличаться, особенно на винде. Нужно откуда-то его получить.

KivApple ★★★★★ ()
Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

все советы Linux only

Вроде как setuptools умеет создавать виндовые инсталляторы.

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

почти советуют - setuptools же и entry_points, остается только на pypi залить пакет.

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

Интересный вопрос. По-моему, «правильно структурировать» это вопрос некроссплатформенный, по крайней мере, в треде все советы Linux only.

www.linux.org.ru нет?

Нет, потому что Питон кросс-платформенный инструмент.

А что никто не советует pypi.python.org? С установкой pip install <package>?

Потому что pypi это сторадж и там кастомного пакета не будет до тех пор, пока автор его туда не зальет.

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

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

Я неточно оформил мысль, my bad. Но у меня утро, что немного оправдывает.

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

Там советуют использовать package_data вместо data_files. Сделал так:

...

metadata_files = []
for d, folders, files in os.walk('share'):
	for f in files:
		metadata_files.append(os.path.join(d, f))

setup(
	...
	package_dir={'mcu-info-util': 'mcu-info-util'},
	package_data={'mcu-info-util': metadata_files},
	...
)

В итоге, несмотря на то что в metadata_files полный список нужных файлов (относительно корня проекта) в пакет ничего кроме кода не попадает.

Ещё по ссылкам пишут, что текущий префикс можно получить из os.prefix. Соответственно, можно просто адресовать data_files относительно этой переменной. Насколько это хорошая идея? Это кроссплатформенно?

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

Вроде победил:

import os
from setuptools import setup

setup(
	name='mcu-info-util',
	version='0.1',
	author='Ivan Kolesnikov',
	author_email='kiv.apple@gmail.com',
	url='https://github.com/KivApple/mcu-info-util',
	packages=['mcu_info_util'],
	package_dir={'mcu_info_util': 'mcu_info_util'},
	package_data={'mcu_info_util': ['metadata/*', 'metadata/*/*', 'metadata/*/*/*', 'metadata/*/*/*/*']},
	entry_points={
		'console_scripts': [
			'mcu-info-util = mcu_info_util.__main__:main'
		]
	}
)

При этом все данные лежат в каталоге metadata, который в свою очередь лежит в каталоге пакета. Пока в коде делаю тупо:

metadata_dir = os.path.join(os.path.dirname(__file__), 'metadata')

Но это, конечно, нужно будет потом исправить.

Однако не очень нравится, что код и данные лежат вместе.

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

Однако не очень нравится, что код и данные лежат вместе.

Не обязательно. Многие пакеты кладут данные в contrib, data и прочие директории. После того как оно приехало на сервер в виде пакета дальше его трогать никто не должен.

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

для получения путей к файлам данным пакета есть функции, см. pkg_resources.resource_filename, напр.

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