2008-11-13 3 views
6

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

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

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 и т. д., чтобы управлять ссылками и содержать фактические ссылки на пути к файлу вне исходных файлов. Это позволяет мне просто предоставлять «использование» директив (эквивалентно импорту Python), не подвергая все ссылки и позволяя повторно использовать ссылки на пути по нескольким сценариям.

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

ответ

4

Простого ответа поставить свой многоразовый код в каталоге сайта-пакетах, который находится в вашей SYS. дорожка.

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

О, и питона 2,6/3,0 добавлена ​​поддержка PEP370, Per-user site-packages Directory

3

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

import Foo 

This question содержит несколько деталей.

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

1

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

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

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

1

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

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

Таким образом, это добавит/дом/Ясон и/USR/доли/some_directory на пути питона при запуске программы.

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

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

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

1

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

0

Мое решение было упаковать одну утилиту, которая будет импортировать модуль: 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