2009-08-11 2 views
274

У меня есть файл под названием tester.py, расположенный по адресу /project.Импортировать файл из подкаталога?

/project имеет подкаталог lib, с файлом под названием BoxTime.py:

/project/tester.py 
/project/lib/BoxTime.py 

Я хочу, чтобы импортировать BoxTime из tester. Я попытался это:

import lib.BoxTime 

Что привело:

Traceback (most recent call last): 
    File "./tester.py", line 3, in <module> 
    import lib.BoxTime 
ImportError: No module named lib.BoxTime 

Любые идеи, как импортировать BoxTime из подкаталога?

EDIT

__init__.py была проблема, но не забывайте ссылаться на BoxTime в lib.BoxTime или использования:

import lib.BoxTime as BT 
... 
BT.bt_function() 

ответ

353

Взгляните на документацию Packages (раздел 6.4) здесь: http://docs.python.org/tutorial/modules.html

Короче говоря, вам нужно положить пустой файл с именем

__init__.py 

в каталоге "lib".

+28

Почему это чувствует * Hacky *? Это то, как питон записывает безопасные/доступные каталоги импорта. – IAbstract

+5

Не только он маркирует безопасные/доступные каталоги импорта, но также предоставляет способ запускать некоторый код инициализации при импорте имени каталога. – Sadjad

+12

Да, это взломанно и даже грязно, и, на мой взгляд, язык не должен накладывать способ загрузки файлов через файловую систему. В PHP мы решили проблему, разрешив коду userland регистрировать несколько функций автозагрузки, вызываемых при отсутствии пространства имен/классов. Тогда сообщество выпустило стандарт PSR-4, и Composer его реализует, и в наши дни никто не должен беспокоиться об этом. И никаких глупых жестко закодированных '__init__' файлов (но если вы этого хотите, просто зарегистрируйте автозагрузку! В этом разница между _hacky_ и _hackable_). –

11

Пробег: import .lib.BoxTime. Для получения дополнительной информации ознакомьтесь с относительным импортом в PEP 328.

+2

Я не думаю, что когда-либо видел этот синтаксис, используемый раньше. Есть ли сильная причина (не) использовать этот метод? – tgray

+1

Почему это не ответ. Конечно, если вы хотите сделать все дело с пакетами, вы должны это сделать. Но это не тот исходный вопрос. –

+0

Это дает мне: ValueError: Попытка относительного импорта в не-пакет – Alex

19

В вашем каталоге lib содержится файл __init__.py?

Python использует __init__.py, чтобы определить, является ли каталог модулем.

108
  • Создайте подкаталог с именем lib.
  • Создайте пустой файл с именем lib\__init__.py.
  • В lib\BoxTime.py написать функцию foo() так:

    def foo(): 
        print "foo!" 
    
  • В коде клиента в каталоге выше lib, написать:

    from lib import BoxTime 
    BoxTime.foo() 
    
  • запустить свой код клиента.Вы получите:

    foo! 
    

Намного позже - в Linux, это будет выглядеть следующим образом:

% cd ~/tmp 
% mkdir lib 
% touch lib/__init__.py 
% cat > lib/BoxTime.py << EOF 
heredoc> def foo(): 
heredoc>  print "foo!" 
heredoc> EOF 
% tree lib 
lib 
├── BoxTime.py 
└── __init__.py 

0 directories, 2 files 
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from lib import BoxTime 
>>> BoxTime.foo() 
foo! 
+0

Не могли бы вы предоставить ссылку на документацию Python, где это объясняется? Благодаря! – Zenon

+1

@ Zenon, попробуйте следующее: docs.python.org/tutorial/modules.html#packages – hughdbrown

32

Вы можете попробовать вставить его в sys.path:

sys.path.insert(0, './lib') 
import BoxTime 
+6

Это здорово, если вы по какой-то причине не можете или не будете создавать файл __init__.py. – jpihl

+1

, похоже, не работает для меня (ошибка «Нет модуля ..») – minsk

+1

Он работает, если вы запустите python из каталога «project». «.» интерпретируется относительно вашего текущего рабочего каталога, а не относительно каталога, в котором находится исполняемый файл. Скажем, 'cd/data',' python ../ project/tester.py'. Тогда это не сработает. – morningstar

0

попробуйте следующее:

from lib import BoxTime

+1

без каких-либо объяснений это не очень полезно. –

6

Я делаю это, который в основном охватывает все случаи (убедитесь, что у вас есть __init__.py в относительном/путь/к/ваш/Библиотека/папки):

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/your/lib/folder") 
import someFileNameWhichIsInTheFolder 
... 
somefile.foo() 


Пример:
у вас в папке проекта:

/root/myproject/app.py 

Вы в другой папке проекта:

/root/anotherproject/utils.py 
/root/anotherproject/__init__.py 

Вы хотите использовать /root/anotherproject/utils.py и вызвать функцию Foo, которая находится в нем.

Так вы пишете в app.py:

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../anotherproject") 
import utils 

utils.foo() 
+1

, если вы используете 'os.path', вы, вероятно, захотите использовать' os.path.join ((os.path.dirname (os.path.realpath (__ file __)), '..', 'anotherproject') ' вместо hardcoding '/' в конкатенации пути. – cowbert

0

Создайте пустой файл __init__.py в подкаталоге/Lib. и добавить в начало основного кода

from __future__ import absolute_import 

затем

import lib.BoxTime as BT 
... 
BT.bt_function() 

или лучше

from lib.BoxTime import bt_function 
... 
bt_function() 
Смежные вопросы