LINUX.ORG.RU

Переносимый python скрипт. Как сделать?

 


2

4

Есть скрипт для копирования фото. В нем используются такие модули:

import argparse
import os
import re
import shutil
import sys
from PIL import Image
from PIL.ExifTags import TAGS

Нужно чтоб этот скрипт работал на любой убунте, и на тех где не установлен python-pil.

Почитала про distutils, не подходит, т.к. он для модулей, а у меня обычный скрипт


Посмотри в сторону pip. Оно умеет ставить зависимости.

Что касается distutils то, по-моему, для скриптов оно вполне годилось. Но умеет ли оно, например, работать с репозиториями и выкачивать зависимости я не помню не знаю.

true_admin ★★★★★
()

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

MrClon ★★★★★
()

Если тебе нужна какая-то библиотека, то носи её с собой или устанавливай. Третьего здесь нет.

spichka ★★★
()

Самый простой вариант после didstutils - воспользоваться virtualenv. А именно:

1. Делаешь виртуалэнв

2. Устанавливаешь все зависимости

4. Делаешь скрипт запуска, который использует интерпретатор virtualenv вместо системного

3. делаешь pip freeze > requirements.txt и кидаешь его рядом со скриптом.

4. На новую дистру перекидываешь либо весь проект вместе с виртуалэнв, либо заного создаешь виртуалэнв и выполняешь pip install -r requirements.txt

Siado ★★★★★
()

Мне одному кажется что все эти пляски, с виртуальными окружениями и прочим, излишни для скрипта? По крайней мере если все нужные модули есть в репах бубунтодебиана.

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

все эти пляски, с виртуальными окружениями и прочим, излишни для скрипта

Тоже так думаю

Jills
() автор топика

таскать за собой pil ?

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

Опокечивать скрипт? Может у нас разные представления о том что такое скрипт, но в моём понимании скрипт что какая-то подсобная мелочёвка на десяток другой строк кода. Ради этого разводить возню с пакетированием не стоит.
Вообще блока импортов волне достаточно что-бы понять что нужно установить такие-то модули (любым удобным пользователю способом). Можно ещё до кучи в коментах написать то-же самое человеческим языком. В крайней случае можно даже привести готовую команду вида sudo apt-get install список пакетов (не-убунтоиды по идее и без этого разберутся).

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

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

neversleep ★★
()

Видел, что уже посоветовали таскать за собой virtualenv. Как по мне, можно сделать проще:

$ wget downloads.buildout.org/2/bootstrap.py

Создаёшь setup.py на подобии этого (если ещё не создан):

from setuptools import setup, find_packages
setup(
    name='имя_пакета_заменяешь_на_своё',
    version='0.0.1',
    packages=find_packages('src'),
    package_dir={'': 'src'},
    install_requires=[
        'Pillow'
    ],
    entry_points={
        'console_scripts': [
            'run=имя_пакета:имя_функции'
        ]
    }
)

Создаёшь директорию src/имя_пакета. Туда ложишь свой скрипт и __init__.py.
В __init__.py определяешь функцию, которая будет выполнять роль точки входа. Её имя должно быть указано в setup.py
Можно сразу весь код в __init__.py положить, тут уже как удобнее будет.

В buildout.cfg:

[buildout]
develop = .
parts = main
show-picked-versions = true
versions=versions
[main]
recipe = zc.recipe.egg
eggs = имя_пакета
interpreter = py
[versions]
Pillow = нужная.версия

Выполняешь python bootstrap.py и bin/buildout. Эти две команды установят setuptools и зависимости, описанные в setup.py, в директорию ./eggs.
Для запуска скрипта нужно будет выполнить bin/run. А для запуска интерпретатора — bin/py.
Если используется третий питон, то вместо python bootstrap.py надо будет выполнить python3 bootstrap.py Теперь можно собрать архив и закинуть на любой ПК.

Почитать про buildout можно тут: http://buildout.org/ Ну найти а доку по setuptools, думаю, не составит труда.

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

Но ведь у них там своя песочница получается, в которой можно что угодно творить. Чем это может быть чревато?

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

Ммм, а как это песночница работает? Ты имеешь в виду настроить pip чтобы он под локальным префиксом ставил? Ну так это надо настраивать, для конечного юзера это гемор. Тут уж проще с virtualenv замутить.

Если же просто сделать pip install то оно положит, например, в /usr/lib/python3.4/site-packages/ .

true_admin ★★★★★
()

А зачем? Просто указать зависимости, юзер сам поставит. А если будут включать скрипт в репозитарий, то зависимости разрулит пакетный менеджер. Не стоит тут велосипеды городить, имхо.

А если юзер не читает документацию, не знает какие у скрипта зависимости и вообще непонятно, где его взял, то ему можно об этом сообщить как нибудь:

try:
    from PIL import Image
    from PIL.ExifTags import TAGS
except:
    print("This script requires 'python-pil' package installed")
    sys.exit(1)

А таскать всё с собой — это windows-way какой-то.

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

Понял. Но тогда, если модуль слишком тухлый в дистрибутиве, то pip поставит свежую версию которая не подхватится, верно? Хотя, не удивлюсь если уже придумали какой-нить более продвинутый импортёр модулей который понимает несколько установленных модулей и выбирает нужный. Есть что-то типа такого?

module = require(modname, version)

По-моему, где-то даже видел что этот require ещё и сам поставит пакет если его нет в системе. А может с javascript путаю...

Вот мой sys.path на старой виртуалке:

# cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.5 LTS"

# python -c 'import sys; print(sys.path)'
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0']

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

Удваиваю этого регистранта. Опачечивания и virtualenv - слишком избыточно для обычного скрипта.

NeverLoved ★★★★★
()

Переносимый python скрипт

Нужно чтоб этот скрипт работал на любой убунте

«Теперь это так называется»

hobbit ★★★★★
()

Есть занятный способ: покидать зависимости в одну папку, зазиповать, и получить исполняемый python-скрипт «все включено».

http://blog.ablepear.com/2012/10/bundling-python-files-into-stand-alone.html

Но вот у конкретно этой графической библиотеки есть обязательные сишные расширения, так что способ не подходит.

Поэтому лучше все-таки закинуть скрипт в пакет, или в инструкцию добавить: «Напишите sudo apt-get install python-pil». Если взять virtualenv, то получится замена шила на мыло: ему обязательно потребуется сишный компилятор, который все равно придется поставить apt-get'ом.

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

Две кружки медовухи ему! Нафига разводить все эти лишние сложности?

Только навороты над импортами это вроде не по PEP8. Да import и сам ругаться хорошо умеет, без костылей.

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

докер конечно же :)

Всё ждал когда это предложат.

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

Опокечивать скрипт?

Почему нет?

└► file /usr/bin/* | grep -ie script | wc -l
593

Каждый из этих 593 скриптов опакечен.

скрипт что какая-то подсобная мелочёвка на десяток другой строк кода

К данному случаю это не относится — слишком много зависимостей.

Хотя сама по себе сборка deb-пакетов — развлекуха та еще.

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

Утилита file показывает тип файла. В эти 593 скорее всего попало вообще всё что не является бинарным файлом или java-приложением.
Перепиши GIMP на python, и он тоже попадёт в список скриптов.
К тому-же многие из этих 593 файлов входят в большие пакеты в которых более одного исполняемого файла.

К данному случаю это не относится — слишком много зависимостей.

Да, целая одна зависимость которой возможно ещё нет в системе. Все эти os и sys всегда уже есть в системе, а если учесть что речь идёт про бубунты (в которых из коробки не мало питонячего софта) скорее всего в свежеустановленной системе не будет только PIL.

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

Утилита file показывает тип файла. В эти 593 скорее всего попало вообще всё что не является бинарным файлом или java-приложением.

Даже одни только abcde, akmods и youtube-dl — уже достаточная иллюстрация того, что в пакетировании скриптов нет ничего сверхъестественного.

Да, целая одна зависимость которой возможно ещё нет в системе.

Умножь на десяток-другой хостов.

Впрочем, можно и ограничиться инструкцией вида sudo apt-get install python-pil.

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

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

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

Даже одни только abcde, akmods и youtube-dl — уже достаточная иллюстрация того, что в пакетировании скриптов нет ничего сверхъестественного.

Только youtube-dl, к примеру, — это не одинокий скрипт, это ещё и мешок модулей под все сайты подряд. А у некоторых ещё и /usr/bin/{firefox,7z} часто оказываются странными скриптами запуска того, что в /usr/lib/… лежит. И ldd не одинок, а идёт с glibc. И так далее. В реальности примеров пакетов с одинокими скриптами буквально кот накакал.

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

Только youtube-dl, к примеру, — это не одинокий скрипт, это ещё и мешок модулей под все сайты подряд

Помню времена, когда он был одиночным скриптом.

В реальности примеров пакетов с одинокими скриптами буквально кот накакал.

Даже если бы такой скрипт в природе был бы всего один, он уже служил бы подтверждением того, что в пакетировании скриптов ничего противоестественного нет.

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

Пакетировать всякую мелочёвку есть смысл что-бы пропихнуть её в репозитории.

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

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

Этож сколько надо скриптов, этож сколько надо хостов что-бы всё это было оправдано.
Так и до докера докатиться можно.

MrClon ★★★★★
()
try:
    from PIL import Image
except ImportError:
    from subprocess import check_call
    check_call('sudo apt-get install -y python-pil', shell=True)
    from PIL import Image
ei-grad ★★★★★
()
Последнее исправление: ei-grad (всего исправлений: 1)

А вообще просто собери скрипт в .deb-пакет, подними свою репку (даже не обязательно PPA) и ставь оттуда.

ei-grad ★★★★★
()
Ответ на: комментарий от hobbit

«Теперь это так называется»

А в чём проблема?

frob ★★★★★
()

годная тема, сам боялся спросить. Я лично использую setuptools :)

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

4. Делаешь скрипт запуска, который использует интерпретатор virtualenv вместо системного

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

Можно ли просто создать requirements.txt с нужными модулями и носить в папке со скриптом, чтоб потом установить зависимости через pip?

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

Конфликтами. Возможно несколько исходов в зависимости от того что куда проинсталлилось. Например, ты поставил более новую версию пакета руками для своего скрипта. А пакетный менеджер об этом не знает и может поставить этот пакет другой версии ещё раз. Результат зависит от того какой пакет найдётся первым и на сколько старая и новая версия совместимы.

true_admin ★★★★★
()

добавить в скрипт установку этих модулей.

erzent ☆☆
()
Ответ на: комментарий от true_admin

ты поставил более новую версию пакета руками для своего скрипта

А разве прекрасный/глобальный/надежный не умеет сразу несколько версий модуля? :(

А пакетный менеджер об этом не знает и может поставить этот пакет другой версии ещё раз.

А зачем тогда нужны пакетные менеджеры ЯП? Только для «песочниц»?

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

А разве прекрасный/глобальный/надежный не умеет сразу несколько версий модуля? :(

А какие вообще умеют? Ну, кроме гентушного. И, по-моему, там одновременно только одна версия активна, не? И вообще, хотелось бы это иметь в самом ЯП из коробки. Чтобы в скрипте можно было прописать, скажем, минимально необходимые версии и чтобы ЯП сам понимал несколько установленных версий. На данный момент всё больше людей это понимают и когда-нить в питоне будет продвинутый import. Собстно, уже сейчас можно такое сделать руками с importlib, но хотелось бы стандартное решение.

А зачем тогда нужны пакетные менеджеры ЯП? Только для «песочниц»?

Тут желательно определиться чем пользоваться: средствами ЯП или же средствами пакетного менеджера. У каждого метода свои плюсы и минусы. Лично я использую сразу оба, доставляя руками только то чего нет в пакетах. Я раньше использовал всякие checkinstall чтобы пакеты создавались автоматически, но щас забил.

Для сложных проектов с кучей зависимостей я рекомендую virtualenv. Ну просто потому что велики шансы что нужных версий в дистрибутиве не окажется и дабы не создвать слакварьпомойку.

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

А какие вообще умеют?
И вообще, хотелось бы это иметь в самом ЯП из коробки

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

Тут желательно определиться чем пользоваться

Это понятно. Видимо стоит брать песочницу, в которой только батарейка ЯП, ну и пользоваться всякими virtualenv.

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