В Python, как я могу эффективно управлять ссылками между файлами скриптов? - PullRequest
6 голосов
/ 13 ноября 2008

У меня есть достаточное количество скриптов Python, которые содержат код многократного использования, на который ссылаются другие скрипты Python. Однако эти сценарии, как правило, разбросаны по разным каталогам, и я считаю несколько утомительным включать (чаще всего несколько) вызовов sys.path.append в мои сценарии верхнего уровня. Я просто хочу предоставить операторы 'import' без дополнительных ссылок на файлы в том же скрипте.

В настоящее время у меня есть это:

import sys
sys.path.append('..//shared1//reusable_foo')
import Foo
sys.path.append('..//shared2//reusable_bar')
import Bar

Мои предпочтения будут следующие:

import Foo
import Bar

Мой опыт в основном связан с платформой .NET, поэтому я привык иметь метафайлы, такие как * .csproj, * .vbproj, * .sln и т. Д., Чтобы управлять и содержать фактические ссылки на пути к файлам вне исходных файлов , Это позволяет мне просто предоставлять директивы using (эквивалентно импорту Python), не раскрывая все ссылки и не позволяя повторно использовать сами ссылки на пути в нескольких сценариях.

Имеет ли Python эквивалентную поддержку для этого и, если нет, каковы некоторые методы и подходы?

Ответы [ 6 ]

4 голосов
/ 13 ноября 2008

Простой ответ - поместить ваш повторно используемый код в каталог site-packages, который находится в вашем sys.path.

Вы также можете расширить путь поиска, добавив файлы .pth где-то на своем пути. Подробнее см. https://docs.python.org/2/install/#modifying-python-s-search-path

О, а в python 2.6 / 3.0 добавлена ​​поддержка PEP370, Каталог пользовательских пакетов для каждого пользователя

3 голосов
/ 13 ноября 2008

Если ваши повторно используемые файлы упакованы (то есть они содержат __init__.py файл), а путь к этому пакету является частью вашего PYTHONPATH или sys.path, тогда вы сможете сделать только

import Foo

В этом вопросе приводится еще несколько подробностей.

(Примечание. Как сказал Джим, вы также можете поместить свой повторно используемый код в каталог site-packages.)

1 голос
/ 14 ноября 2008

Самый простой способ - установить (или добавить) PYTHONPATH и поместить (или символическую ссылку) ваши модули и пакеты в путь, содержащийся в PYTHONPATH.

1 голос
/ 13 ноября 2008

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

[server]
PYPATH_APPEND: /home/jason:/usr/share/some_directory

Таким образом, это добавит / home / jason и / usr / share / some_directory к пути python при запуске программы.

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

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

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

1 голос
/ 13 ноября 2008

Вы можете поместить материал многократного использования в site-packages. Это абсолютно прозрачно, поскольку по умолчанию оно sys.path.

Вы можете поместить someName.pth файлы в site-packages. В этих файлах есть каталог, в котором живут ваши реальные многократно используемые материалы. Это также совершенно прозрачно. И не включает в себя дополнительный шаг установки изменения в site-packages.

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

0 голосов
/ 14 ноября 2008

Мое решение состояло в том, чтобы упаковать одну утилиту, которая импортировала бы модуль: my_util в пакетах сайта

import my_util

foo = myutil.import_script('..//shared1//reusable_foo')
if foo == None:
    sys.exit(1)


def import_script(script_path, log_status = True):
    """
    imports a module and returns the handle
    """
    lpath = os.path.split(script_path)

    if lpath[1] == '':
        log('Error in script "%s" in import_script' % (script_path))
        return None


    #check if path is already in sys.path so we don't repeat
    npath = None
    if lpath[0] == '':
        npath = '.'
    else:
        if lpath[0] not in sys.path:
            npath = lpath[0]

    if npath != None:
        try:
            sys.path.append(npath)
        except:
            if log_status == True:
                log('Error adding path "%s" in import_script' % npath)
            return None

    try:   
        mod =  __import__(lpath[1])
    except:
        error_trace,error_reason =  FormatExceptionInfo()
        if log_status == True:
            log('Error importing "%s" module in import_script: %s' % (script_path, error_trace + error_reason))
        sys.path.remove(npath)
        return None

    return mod
...