Импорт в Python проект с документами - PullRequest
4 голосов
/ 03 марта 2010

У меня есть проект Python со следующей структурой каталогов:

/(some files)
/model/(python files)
/tools/(more python files)
...

Итак, у меня есть файлы Python в нескольких подкаталогах, и есть некоторые зависимости между каталогами: инструменты используются моделями и т. д. Теперь моя проблема в том, что я хочу сделать тесты для обеих моделей и инструментов , и я хочу иметь возможность запускать тесты из командной строки следующим образом: . / model / car.py . Я могу заставить это работать, но только с грязным шаблонным кодом. мне бы хотелось узнать, что является правильным способом, или есть ли какой-нибудь?

Вопрос : Как мне написать свой импорт?

Thanx. Вот пример ...

Содержимое tools / tool.py :

#!/usr/bin/env python
"""
   >>> is_four(21)
   False
   >>> is_four(4)
   True
"""

def is_four(val):
    return val == 4

if __name__ == '__main__':
    import doctest
    doctest.testmod()

... и модель / car.py :

#!/usr/bin/env python   
"""
   >>> car = Car()
   >>> car.ok()
   True
"""

from tools.tool import *

class Car(object):
    def __init__(self):
        self.tire_count = 4
    def ok(self):
        return is_four(self.tire_count)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

Добавляя следующие строки в начале car.py, он работает, но выглядит не очень хорошо. (

if __name__ == '__main__':
    import sys
    import os
    sys.path.append(os.path.abspath(os.path.dirname('..')))

Ответы [ 3 ]

2 голосов
/ 04 марта 2010

То, что вы пытаетесь сделать, это относительный импорт. Он отлично работает в Python, , но на уровне модулей, а не на уровне файловой системы. Я знаю, это сбивает с толку.

Это означает, что если вы запускаете скрипт в подкаталоге, он не видит верхние каталоги, потому что для запущенного скрипта корень модуля - это текущий каталог: верхнего модуля нет.

Так для чего нужен относительный импорт?

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

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

Возможное решение вашей проблемы - удалить блок if __name__ == "__main__" и создать /tests.py:

.
import doctest
from model import car
from tools import tool

doctest.testmod(car)
doctest.testmod(tool)

Тогда запустите тоже, запустите все тесты.

В конечном итоге вы захотите автоматизировать процесс, простое решение - использовать unittest, чтобы вы могли создавать наборы тестов и просто добавлять имена модулей, которые вы хотите протестировать:

import unittest
import doctest

modules = ("model.car", 
           "tools.tool")

suite = unittest.TestSuite()
for mod in modules:
    suite.addTest(doctest.DocTestSuite(mod))
runner = unittest.TextTestRunner()
runner.run(suite)

Другое решение (рекомендуется) - использовать инструмент, такой как nose , который автоматизирует это для вас.

easy_install nose
nosetests --with-doctest # done :-)

И, кстати, избегайте from x import *. Это работает для быстрых сценариев, но когда ваша программа будет расти, вам действительно нужно будет явно указать, что вы импортируете. Либо import x, либо from x import y

1 голос
/ 03 марта 2010

Используйте пакеты. Добавьте файл __init__.py в ваш рабочий каталог и все подпапки, после чего ваш импорт выполнит поиск родительских каталогов, если не найдет модуль в текущем каталоге.

См. http://www.network -theory.ru/docs / pytut / Packages.html

Также этот вопрос является дубликатом:

Импорт модуля из относительного пути

0 голосов
/ 03 марта 2010

Не офигите sys.path таким образом. Вместо этого либо используйте $PYTHONPATH для принудительного входа в базовый каталог при вызове python, либо используйте python -m model.car из этого каталога.

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