Python ImportError: нет модуля с именем Проблема

Я использую Python 2.6.1 в Windows XP SP3. Моя IDE — PyCharm 1.0-Beta 2, сборка PY-96.1055.

Я храню свои файлы .py в каталоге с именем «src»; у него есть файл __init__.py, который пуст, за исключением атрибута "__author__" вверху.

Один из них называется Matrix.py:

#!/usr/bin/env python
"""
"Core Python Programming" chapter 6.
A simple Matrix class that allows addition and multiplication
"""
__author__ = 'Michael'
__credits__ = []
__version__ = "1.0"
__maintainer__ = "Michael"
__status__ = "Development"

class Matrix(object):
    """
    exercise 6.16: MxN matrix addition and multiplication
    """
    def __init__(self, rows, cols, values = []):
        self.rows = rows
        self.cols = cols
        self.matrix = values

    def show(self):
        """ display matrix"""
        print '['
        for i in range(0, self.rows):
            print '(',
            for j in range(0, self.cols-1):
                print self.matrix[i][j], ',',
            print self.matrix[i][self.cols-1], ')'
        print ']'

    def get(self, row, col):
        return self.matrix[row][col]

    def set(self, row, col, value):
        self.matrix[row][col] = value

    def rows(self):
        return self.rows

    def cols(self):
        return self.cols

    def add(self, other):
        result = []
        for i in range(0, self.rows):
            row = []
            for j in range(0, self.cols):
                row.append(self.matrix[i][j] + other.get(i, j))
            result.append(row)
        return Matrix(self.rows, self.cols, result)

    def mul(self, other):
        result = []
        for i in range(0, self.rows):
            row = []
            for j in range(0, other.cols):
                sum = 0
                for k in range(0, self.cols):
                    sum += self.matrix[i][k]*other.get(k,j)
                row.append(sum)
            result.append(row)
        return Matrix(self.rows, other.cols, result)

    def __cmp__(self, other):
        """
        deep equals between two matricies
        first check rows, then cols, then values
        """
        if self.rows != other.rows:
            return self.rows.cmp(other.rows)
        if self.cols != other.cols:
            return self.cols.cmp(other.cols)
        for i in range(0, self.rows):
            for j in range(0, self.cols):
                if self.matrix[i][j] != other.get(i,j):
                    return self.matrix[i][j] == (other.get(i,j))
        return True # if you get here, it means size and values are equal



if __name__ == '__main__':
    a = Matrix(3, 3, [[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    b = Matrix(3, 3, [[6, 5, 4], [1, 1, 1], [2, 1, 0]])
    c = Matrix(3, 3, [[2, 0, 0], [0, 2, 0], [0, 0, 2]])
    a.show()
    b.show()
    c.show()
    a.add(b).show()
    a.mul(c).show()

Я создал новый каталог с именем «test», в котором также есть файл __init__.py, который пуст, за исключением атрибута «__author__» вверху. Я создал MatrixTest.py для объединения моего класса Matrix:

#!/usr/bin/env python
"""
Unit test case for Matrix class
See http://jaynes.colorado.edu/PythonGuidelines.html#module_formatting for Python coding guidelines
"""

import unittest #use my unittestfp instead for floating point
from src import Matrix # Matrix class to be tested

__author__ = 'Michael'
__credits__ = []
__license__ = "GPL"
__version__ = "1.0"
__maintainer__ = "Michael"
__status__ = "Development"

class MatrixTest(unittest.TestCase):
    """Unit tests for Matrix class"""
    def setUp(self):
        self.a = Matrix.Matrix(3, 3, [[1, 2, 3], [4, 5, 6], [7, 8, 9]])
        self.b = Matrix.Matrix(3, 3, [[6, 5, 4], [1, 1, 1], [2, 1, 0]])
        self.c = Matrix.Matrix(3, 3, [[2, 0, 0], [0, 2, 0], [0, 0, 2]])

    def testAdd(self):
        expected = Matrix.Matrix(3, 3, [[7, 7, 7], [5, 6, 7], [9, 9, 9]])    # need to learn how to write equals for Matrix
        self.a.add(self.b)
        assert self.a == expected

if __name__ == '__main__':    #run tests if called from command-line
    suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
    unittest.TextTestRunner(verbosity=2).run(suite)

Тем не менее, когда я пытаюсь запустить свой MatrixTest, я получаю эту ошибку:

C:\Tools\Python-2.6.1\python.exe "C:/Documents and Settings/Michael/My Documents/Projects/Python/learning/core/test/MatrixTest.py"
Traceback (most recent call last):
  File "C:/Documents and Settings/Michael/My Documents/Projects/Python/learning/core/test/MatrixTest.py", line 8, in <module>
    from src import Matrix # Matrix class to be tested
ImportError: No module named src

Process finished with exit code 1

Все, что я читал, говорит мне, что наличие init.py во всех моих каталогах должно позаботиться об этом.

Если кто-то может указать, что я пропустил, я был бы очень признателен.

Я также хотел бы получить совет о том, как лучше всего разрабатывать и поддерживать классы исходного кода и модульного тестирования. Я думаю об этом так же, как обычно, когда пишу Java: каталоги /src и /test с идентичными структурами пакетов внизу. Является ли это «питоновским» мышлением или мне следует рассмотреть другую схему организации?

ОБНОВИТЬ:

Спасибо тем, кто ответил, вот решение, которое сработало для меня:

  1. Изменить импорт на from src import Matrix # Matrix class to be tested
  2. Добавьте sys.path в качестве переменной среды в мою конфигурацию unittest с каталогами ./src и ./test, разделенными точкой с запятой.
  3. Измените объявления в MatrixTest.py, как показано.

person duffymo    schedule 05.09.2010    source источник
comment
Вы говорите, что ваши файлы хранятся в папке src? C:\Tools\Python-2.6.1\python.exe C:/Documents and Settings/Michael/My Documents/Projects/Python/learning/core/test/MatrixTest.py   -  person awithrow    schedule 05.09.2010
comment
Используйте 1_. См. stackoverflow.com /вопросы/24622041/   -  person jrc    schedule 25.11.2016


Ответы (2)


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

Запуск программ в каталоге src мог работать, потому что Python автоматически вставляет каталог сценария, который в данный момент выполняется, в sys.path. Таким образом, импорт модулей в src будет работать, если вы также выполняете скрипт, который находится в src.

Но теперь, когда вы запускаете скрипт из test, каталог test автоматически добавляется в sys.path, а src — нет.

Все каталоги, перечисленные в PYTHONPATH, добавляются в sys.path, и Python ищет sys.path, чтобы найти модули.

Кроме того, если вы скажете

from src import Matrix

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

person unutbu    schedule 05.09.2010
comment
@Cristian: я поместил import sys; print(sys.path) в файл с именем test.py. Затем я побежал cd /some/other/dir; python /path/to/test.py. Первый указанный путь — /path/to, а не /some/other/dir. Таким образом, появляется каталог скрипта, а не CWD, который добавляется в sys.path. - person unutbu; 05.09.2010
comment
@~unutbu: ты прав! Причиной моего комментария был этот фрагмент из учебника: Когда импортируется модуль с именем spam, интерпретатор ищет файл с именем spam.py в текущем каталоге, а затем в списке каталогов, указанном переменной среды PYTHONPATH.. Я думаю, кто-то следует перефразировать его менее двусмысленным образом. - person Cristian Ciupitu; 05.09.2010
comment
@Cristian: Хм, это, конечно, сбивает с толку. (Правда, пытается уточнить во втором абзаце). Вот еще одна ссылка на документы; этот, я думаю, понятнее: docs.python.org/library/sys.html #sys.path - person unutbu; 05.09.2010
comment
Спасибо, ~унутбу. Решение, к которому вы и Кристиан Чиупиту привели меня, добавлено к моему вопросу. - person duffymo; 05.09.2010
comment
@~unutbu: да, второй абзац проясняет ситуацию, хотя, когда я читал учебник давным-давно, его не существовало или я как-то пропустил его. В любом случае, я сообщил об этом команде документации, и, возможно, они перефразируют этот раздел, чтобы сделать его более понятным. Также спасибо за ссылку sys.path! - person Cristian Ciupitu; 05.09.2010

Что касается рекомендаций, PycURL использует каталог tests на том же уровне, что и основной исходный код. С другой стороны, такие проекты, как Twisted или sorl-thumbnail использовать подкаталог test(s) в основном исходном коде.

На другую половину вопроса уже ответил ~unutbu.

person Cristian Ciupitu    schedule 05.09.2010
comment
Привет Кристиан, Спасибо за пример. Я предпочитаю, как вы это делаете: /src и /test на одном уровне. - person duffymo; 05.09.2010