Как l oop импортировать пакеты в определение функции? - PullRequest
0 голосов
/ 27 марта 2020

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

Вот мой код без l oop:

def pkgs_install():
    import subprocess
    import sys

    try:
        import pandas as pd
        print('{} is already installed'.format('Pandas'))
    except ImportError:
        print('{} is not installed and has to be installed'.format('Pandas'))
        subprocess.call([sys.executable, '-m', 'pip', 'install', 'pandas'])
    finally:
        import pandas as pd
        print('{} is properly installed'.format('Pandas'))

    try:
        import numpy
        print('{} is already installed'.format('Numpy'))
    except ImportError:
        print('{} is not installed and has to be installed'.format('Numpy'))
        subprocess.call([sys.executable, '-m', 'pip', 'install', 'numpy'])
    finally:
        import numpy
        print('{} is properly installed'.format('Numpy'))

    print("All packages have been imported. You're good to go!")

Этот код работает правильно, но теперь создание l oop намного сложнее. Я попробовал кусок кода, но я застрял. Вот мой код:

def pkgs_install():
    import subprocess
    import sys
    pkgs = {'pandas': 'pd', 'numpy': 'np'}
    for p in pkgs:
        s = pkgs[p]
        try:
            import p as s
            print('{} is already installed'.format(p))
        except ImportError:
            print('{} is not installed and has to be installed'.format(p))
            subprocess.call([sys.executable, '-m', 'pip', 'install', p])
        finally:
            import p as s
            print('{} is properly installed'.format(p))

    print("All packages have been imported. You're good to go!")

Кто-нибудь знает, как решить эту проблему?

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

вы можете использовать библиотеку importlib для импорта модулей по имени.

import importlib
def pkgs_install():
    import subprocess
    import sys
    pkgs = {'pandas': 'pd', 'numpy': 'np'}
    for p in pkgs:
        s = pkgs[p]
        try:
            s = importlib.import_module(p)
            print('{} is already installed'.format(p))
        except ImportError:
            print('{} is not installed and has to be installed'.format(p))
            subprocess.call([sys.executable, '-m', 'pip', 'install', p])
        finally:
            s = importlib.import_module(p)
            print('{} is properly installed'.format(p))

    print("All packages have been imported. You're good to go!")
0 голосов
/ 27 марта 2020

Я бы не советовал пытаться динамически вызывать pip из Python программы, подобной этой. Есть две причины:

  1. Кажется плохой формой вносить такие агрессивные изменения в среду пользователей. Пусть пользователь сам решит, хотят ли они установить эти библиотеки.
  2. Для системы пользователей возможно множество различных конфигураций, и мы не можем учитывать каждую возможную настройку 1 . Это рискует сломать вещи и оставить беспорядок (см. Пункт # 1)

Позвольте мне спросить вас: скажем, этому модулю нужна какая-то библиотека, и он обнаруживает, что она недоступна. Это можно восстановить (каким-либо иным способом, кроме принудительной установки отсутствующей библиотеки)? Под «восстанавливаемым» я имею в виду: сможет ли модуль по-прежнему делать что-то полезное или единственным результатом будет отображение сообщения об ошибке и выход? Обычно отсутствующая библиотека является фатальной ошибкой, так как мы импортируем вещи, потому что они нужны нам, а не для удовольствия.

Если это невозможно восстановить, то не поймайте это. Это подавляет полезную информацию отладки, на которую пользователь мог бы воздействовать в противном случае. Если вам нужно его перехватить (возможно, для отображения пользовательского сообщения об ошибке или для записи исключения в файл), то raise то же исключение в конце блока except.

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


Редактировать
В комментируя этот ответ, OP добавил дополнительную информацию, которая объясняет, что истинная цель этого упражнения заключается в том, чтобы позволить программе python быть упакованной таким образом, чтобы ее могли использовать другие лица, не вынуждая их устанавливать дополнительные модули.

Это очень распространенная потребность, и у нее очень зрелое и простое в использовании решение: PyInstaller . Он работает для нескольких целевых платформ и поддерживает все распространенные версии Python. Он с открытым исходным кодом и устанавливается из PyPI:

pip install pyinstaller

Он поддерживает matplotlib, numpy и, вероятно, pandas (хотя он не указан как поддерживаемый пакет , я должен предположить, что если первые 2 пакета будут работать, pandas тоже будет).

Вот официальный сайт документации .


1: Возможно, модуль имеет расширение C и требует компилятора. Возможно, пользователь установил указанную c версию библиотеки в нестандартном месте. Возможно, версия, в которой нуждается ваш пакет, не совместима с другими библиотеками, которые уже установлены. Может быть [любая из десятков вещей, которые могут go ошибаться] ......

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...