LPTHW ex49 在单元测试中得到 AttributeError
LPTHW ex49 get AttributeError in unit test
我正在练习 Learn Python th Hard Way 一书中的 ex49 练习。
我在 nosetest 中得到了 AttributeError,而我可以在 python shell 中通过执行命令。
我在 Ubuntu 15.10 中编码,python 版本是 3.4.3。
目录结构如下:
.:
bin docs ex49 lexicon.py parser.py readme setup.py tests
./bin:
./docs:
./ex49:
__init__.py
./tests:
ex49_test.py __init__.py
lexicon.py:
#!/usr/bin/env python
# encoding: utf-8
direction_base = ['north', 'south', 'west', 'east', 'down', 'up', 'left', 'right', 'back']
verb_base = ['go', 'kill', 'eat', 'open']
stop_base = ['the', 'in', 'of', 'it']
noun_base = ['door', 'bear', 'princess', 'carbinet']
def convert_number(s):
try:
return int(s)
except ValueError:
return None
def scan(strInput):
wordList = strInput.lower().split(' ')
resultSentence = []
for word in wordList:
if word in direction_base:
resultSentence.append(('direction', word))
elif word in verb_base:
resultSentence.append(('verb', word))
elif word in stop_base:
resultSentence.append(('stop', word))
elif word in noun_base:
resultSentence.append(('noun', word))
elif convert_number(word) is not None:
resultSentence.append(('number', int(word)))
else:
resultSentence.append(('error', word))
return resultSentence
parser.py:
#!/usr/bin/env python
# encoding: utf-8
class ParserError(Exception):
pass
class Sentence(object):
def __init__(self, subject, verb, number, object):
# remember we take ('noun','princess') tuples and convert them
self.subject = subject[1]
self.verb = verb[1]
self.number = number[1]
self.object = object[1]
def to_tuple(self):
return (self.subject, self.verb, self.number, self.object)
def peek(word_list):
if word_list:
word = word_list[0]
return word[0]
else:
return None
def match(word_list, expecting):
if word_list:
word = word_list.pop(0)
if word[0] == expecting:
return word
else:
return None
else:
return None
def skip(word_list, word_type):
while peek(word_list) == word_type:
match(word_list, word_type)
def parse_verb(word_list):
skip(word_list, 'stop')
if peek(word_list) == 'verb':
return match(word_list, 'verb')
else:
raise ParserError("Expected a verb next.")
def parse_object(word_list):
skip(word_list, 'stop')
next_item = peek(word_list)
if next_item == 'noun':
return match(word_list, 'noun')
elif next_item == 'direction':
return match(word_list, 'direction')
else:
raise ParserError("Expected a noun or direction next.")
def parse_number(word_list, number):
skip(word_list, 'stop')
if peek(word_list) == 'number':
return match(word_list, 'number')
else:
return ('number', 1)
def parse_subject(word_list, subj):
verb = parse_verb(word_list)
number = parse_number(word_list)
obj = parse_object(word_list)
return Sentence(subj, verb, number, obj)
def parse_sentence(word_list):
skip(word_list, 'stop')
start_item = peek(word_list)
if start_item == 'noun':
subj = match(word_list, 'noun')
return parse_subject(word_list, subj)
elif start_item == 'verb':
# assume the subject is the player then
return parse_subject(word_list, ('noun', 'player'))
else:
raise ParserError("Must start with subject, object, or verb not: %s" % start_item)
ex49_test.py:
#!/usr/bin/env python
# encoding: utf-8
from nose.tools import *
import lexicon
import parser
def test_sentence_obj():
s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
assert_equal(s.subject, 'bear')
assert_equal(s.verb, 'eat')
assert_equal(s.number, 1)
assert_equal(s.object, 'door')
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_peek():
word_list = lexicon.scan('princess')
assert_equal(parser.peek(word_list), 'noun')
assert_equal(parser.peek(None), None)
def test_match():
word_list = lexicon.scan('princess')
assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
assert_equal(parser.match(word_list, 'stop'), None)
assert_equal(parser.match(None, 'noun'), None)
def test_skip():
word_list = lexicon.scan('bear eat door')
assert_equal(word_list, [('noun', 'bear'), ('verb', 'eat'), ('noun', 'door')])
parser.skip(word_list, 'noun')
assert_equal(word_list, [('verb', 'eat'), ('noun', 'door')])
def test_parse_verb():
word_list = lexicon.scan('it eat door')
assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
word_list = lexicon.scan('bear eat door')
assert_raise(parser.ParserError, parser.parse_verb, word_list)
def test_parse_object():
word_list = lexicon.scan('the door')
assert_equal(parser.parse_object(word_list), ('noun', 'door'))
word_list = lexicon.scan('the east')
assert_equal(parser.parse_object(word_list), ('direction', 'east'))
word_list = lexicon.scan('the it')
assert_raise(parser.ParserError, parser.parse_object, word_list)
def test_parse_subject():
word_list = lexicon.scan('eat door')
subj = ('noun', 'bear')
s = parser.parse_subject(word_list, subj)
assert_raise(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_parse_sentence():
word_list = lexicon.scan('the bear eat door')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
word_list = lexicon.scan('in the door')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('player', 'eat', 1, 'door'))
word_list = lexicon.scan('north eat door')
assert_equal(parser.ParserError, parser.parse_sentence, word_list)
def test_unknown_words():
word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_number():
word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 5, 'door'))
执行错误:
~/Documents/python3/practice/ex49$ nosetests3 tests/
EEEEEEEEEE
======================================================================
ERROR: tests.ex49_test.test_sentence_obj
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 8, in test_sentence_obj
s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'Sentence'
======================================================================
ERROR: tests.ex49_test.test_peek
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 17, in test_peek
assert_equal(parser.peek(word_list), 'noun')
AttributeError: 'module' object has no attribute 'peek'
======================================================================
ERROR: tests.ex49_test.test_match
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 22, in test_match
assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
AttributeError: 'module' object has no attribute 'match'
======================================================================
ERROR: tests.ex49_test.test_skip
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 29, in test_skip
parser.skip(word_list, 'noun')
AttributeError: 'module' object has no attribute 'skip'
======================================================================
ERROR: tests.ex49_test.test_parse_verb
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 34, in test_parse_verb
assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
AttributeError: 'module' object has no attribute 'parse_verb'
======================================================================
ERROR: tests.ex49_test.test_parse_object
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 40, in test_parse_object
assert_equal(parser.parse_object(word_list), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'parse_object'
======================================================================
ERROR: tests.ex49_test.test_parse_subject
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 49, in test_parse_subject
s = parser.parse_subject(word_list, subj)
AttributeError: 'module' object has no attribute 'parse_subject'
======================================================================
ERROR: tests.ex49_test.test_parse_sentence
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 54, in test_parse_sentence
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
======================================================================
ERROR: tests.ex49_test.test_unknown_words
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 64, in test_unknown_words
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
======================================================================
ERROR: tests.ex49_test.test_number
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 69, in test_number
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
----------------------------------------------------------------------
Ran 10 tests in 0.007s
FAILED (errors=10)
你的问题出在parser
模块命名上。不幸的是,python 中有一个内置的 parser
模块:尝试在任何文件夹中 运行ning python 和 运行 import parser
。现在检查 parser.__file__
以查看它指的是哪个实际模块:对我来说它指的是:
>>> import parser
>>> parser.__file__
'/usr/lib/python2.7/lib-dynload/parser.x86_64-linux-gnu.so'
所以你的 ex49_test.py
选择了错误的 parser
这就是 python 试图告诉你的: AttributeError: 'module' object has no attribute 'match'
意味着在这个模块中没有 match
方法。将解析器重命名为其他名称,看看生活是否变得更好。
我正在练习 Learn Python th Hard Way 一书中的 ex49 练习。 我在 nosetest 中得到了 AttributeError,而我可以在 python shell 中通过执行命令。 我在 Ubuntu 15.10 中编码,python 版本是 3.4.3。 目录结构如下:
.:
bin docs ex49 lexicon.py parser.py readme setup.py tests
./bin:
./docs:
./ex49:
__init__.py
./tests:
ex49_test.py __init__.py
lexicon.py:
#!/usr/bin/env python
# encoding: utf-8
direction_base = ['north', 'south', 'west', 'east', 'down', 'up', 'left', 'right', 'back']
verb_base = ['go', 'kill', 'eat', 'open']
stop_base = ['the', 'in', 'of', 'it']
noun_base = ['door', 'bear', 'princess', 'carbinet']
def convert_number(s):
try:
return int(s)
except ValueError:
return None
def scan(strInput):
wordList = strInput.lower().split(' ')
resultSentence = []
for word in wordList:
if word in direction_base:
resultSentence.append(('direction', word))
elif word in verb_base:
resultSentence.append(('verb', word))
elif word in stop_base:
resultSentence.append(('stop', word))
elif word in noun_base:
resultSentence.append(('noun', word))
elif convert_number(word) is not None:
resultSentence.append(('number', int(word)))
else:
resultSentence.append(('error', word))
return resultSentence
parser.py:
#!/usr/bin/env python
# encoding: utf-8
class ParserError(Exception):
pass
class Sentence(object):
def __init__(self, subject, verb, number, object):
# remember we take ('noun','princess') tuples and convert them
self.subject = subject[1]
self.verb = verb[1]
self.number = number[1]
self.object = object[1]
def to_tuple(self):
return (self.subject, self.verb, self.number, self.object)
def peek(word_list):
if word_list:
word = word_list[0]
return word[0]
else:
return None
def match(word_list, expecting):
if word_list:
word = word_list.pop(0)
if word[0] == expecting:
return word
else:
return None
else:
return None
def skip(word_list, word_type):
while peek(word_list) == word_type:
match(word_list, word_type)
def parse_verb(word_list):
skip(word_list, 'stop')
if peek(word_list) == 'verb':
return match(word_list, 'verb')
else:
raise ParserError("Expected a verb next.")
def parse_object(word_list):
skip(word_list, 'stop')
next_item = peek(word_list)
if next_item == 'noun':
return match(word_list, 'noun')
elif next_item == 'direction':
return match(word_list, 'direction')
else:
raise ParserError("Expected a noun or direction next.")
def parse_number(word_list, number):
skip(word_list, 'stop')
if peek(word_list) == 'number':
return match(word_list, 'number')
else:
return ('number', 1)
def parse_subject(word_list, subj):
verb = parse_verb(word_list)
number = parse_number(word_list)
obj = parse_object(word_list)
return Sentence(subj, verb, number, obj)
def parse_sentence(word_list):
skip(word_list, 'stop')
start_item = peek(word_list)
if start_item == 'noun':
subj = match(word_list, 'noun')
return parse_subject(word_list, subj)
elif start_item == 'verb':
# assume the subject is the player then
return parse_subject(word_list, ('noun', 'player'))
else:
raise ParserError("Must start with subject, object, or verb not: %s" % start_item)
ex49_test.py:
#!/usr/bin/env python
# encoding: utf-8
from nose.tools import *
import lexicon
import parser
def test_sentence_obj():
s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
assert_equal(s.subject, 'bear')
assert_equal(s.verb, 'eat')
assert_equal(s.number, 1)
assert_equal(s.object, 'door')
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_peek():
word_list = lexicon.scan('princess')
assert_equal(parser.peek(word_list), 'noun')
assert_equal(parser.peek(None), None)
def test_match():
word_list = lexicon.scan('princess')
assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
assert_equal(parser.match(word_list, 'stop'), None)
assert_equal(parser.match(None, 'noun'), None)
def test_skip():
word_list = lexicon.scan('bear eat door')
assert_equal(word_list, [('noun', 'bear'), ('verb', 'eat'), ('noun', 'door')])
parser.skip(word_list, 'noun')
assert_equal(word_list, [('verb', 'eat'), ('noun', 'door')])
def test_parse_verb():
word_list = lexicon.scan('it eat door')
assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
word_list = lexicon.scan('bear eat door')
assert_raise(parser.ParserError, parser.parse_verb, word_list)
def test_parse_object():
word_list = lexicon.scan('the door')
assert_equal(parser.parse_object(word_list), ('noun', 'door'))
word_list = lexicon.scan('the east')
assert_equal(parser.parse_object(word_list), ('direction', 'east'))
word_list = lexicon.scan('the it')
assert_raise(parser.ParserError, parser.parse_object, word_list)
def test_parse_subject():
word_list = lexicon.scan('eat door')
subj = ('noun', 'bear')
s = parser.parse_subject(word_list, subj)
assert_raise(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_parse_sentence():
word_list = lexicon.scan('the bear eat door')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
word_list = lexicon.scan('in the door')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('player', 'eat', 1, 'door'))
word_list = lexicon.scan('north eat door')
assert_equal(parser.ParserError, parser.parse_sentence, word_list)
def test_unknown_words():
word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
def test_number():
word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
s = parser.parse_sentence(word_list)
assert_equal(s.to_tuple(), ('bear', 'eat', 5, 'door'))
执行错误:
~/Documents/python3/practice/ex49$ nosetests3 tests/
EEEEEEEEEE
======================================================================
ERROR: tests.ex49_test.test_sentence_obj
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 8, in test_sentence_obj
s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'Sentence'
======================================================================
ERROR: tests.ex49_test.test_peek
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 17, in test_peek
assert_equal(parser.peek(word_list), 'noun')
AttributeError: 'module' object has no attribute 'peek'
======================================================================
ERROR: tests.ex49_test.test_match
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 22, in test_match
assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
AttributeError: 'module' object has no attribute 'match'
======================================================================
ERROR: tests.ex49_test.test_skip
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 29, in test_skip
parser.skip(word_list, 'noun')
AttributeError: 'module' object has no attribute 'skip'
======================================================================
ERROR: tests.ex49_test.test_parse_verb
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 34, in test_parse_verb
assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
AttributeError: 'module' object has no attribute 'parse_verb'
======================================================================
ERROR: tests.ex49_test.test_parse_object
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 40, in test_parse_object
assert_equal(parser.parse_object(word_list), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'parse_object'
======================================================================
ERROR: tests.ex49_test.test_parse_subject
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 49, in test_parse_subject
s = parser.parse_subject(word_list, subj)
AttributeError: 'module' object has no attribute 'parse_subject'
======================================================================
ERROR: tests.ex49_test.test_parse_sentence
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 54, in test_parse_sentence
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
======================================================================
ERROR: tests.ex49_test.test_unknown_words
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 64, in test_unknown_words
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
======================================================================
ERROR: tests.ex49_test.test_number
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 69, in test_number
s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'
----------------------------------------------------------------------
Ran 10 tests in 0.007s
FAILED (errors=10)
你的问题出在parser
模块命名上。不幸的是,python 中有一个内置的 parser
模块:尝试在任何文件夹中 运行ning python 和 运行 import parser
。现在检查 parser.__file__
以查看它指的是哪个实际模块:对我来说它指的是:
>>> import parser
>>> parser.__file__
'/usr/lib/python2.7/lib-dynload/parser.x86_64-linux-gnu.so'
所以你的 ex49_test.py
选择了错误的 parser
这就是 python 试图告诉你的: AttributeError: 'module' object has no attribute 'match'
意味着在这个模块中没有 match
方法。将解析器重命名为其他名称,看看生活是否变得更好。