2011-07-25 73 views
2

有一個ImportError有可能讓我發瘋。這種情況是這樣的:Python模塊的路徑:導入錯誤在mako模板中引發

tests/ 
    testWebsite.py 
website/ 
    __init__.py 
    __main__.py 
    _webtools/ 
     __init__.py 
     templatedefs.py 
     ... 
    _templates/ 
     base.mako 
     article.mako 
     ... 

的代碼(沒有測試目錄,我毫不猶豫地提交,問題解決之前)在線瀏覽:https://github.com/Boldewyn/website/

當我呼叫python -m website.__main__ build時,主例程使用website/_templates下的模板從某些輸入靜態HTML文件創建。這在任何給定的目錄中都能正常工作。

但是,在tests/testWebsite.py我有一個單元測試,它也應該運行相同的東西。但是那裏的Mako模板會引發文件的導入錯誤,在另一種情況下導入的文件很好。

$ head -n 5 website/_templates/article.mako 
# -*- coding: utf-8 -*- 
<%! 
from website._webtools.templatedefs import strip_tags 
%> 
<%inherit file="base.mako" /> 

運行測試,然後得出:

$ python -m unittest tests.testWebsite 
... 
ERROR: test_initial_build (tests.testWebsite.BuildTestCase) 
Check, if building directly after bootstrap works 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "tests/testWebsite.py", line 99, in test_initial_build 
    File "website/_webtools/build.py", line 89, in build 
    article.save(articles=articles) 
    File "website/_webtools/articles.py", line 514, in save 
    template_engine.render_article(self, **ctx) 
    File "website/_webtools/templates.py", line 52, in render_article 
    r.render_article(article, **ctx) 
    File "website/_webtools/templates.py", line 277, in render_article 
    tpl = self.lookup.get_template(filename) 
    File "/usr/lib/python2.7/dist-packages/mako/lookup.py", line 217, in get_template 
    return self._load(srcfile, uri) 
    File "/usr/lib/python2.7/dist-packages/mako/lookup.py", line 277, in _load 
    **self.template_args) 
    File "/usr/lib/python2.7/dist-packages/mako/template.py", line 205, in __init__ 
    module = self._compile_from_file(path, filename) 
    File "/usr/lib/python2.7/dist-packages/mako/template.py", line 249, in _compile_from_file 
    filename) 
    File "/usr/lib/python2.7/dist-packages/mako/template.py", line 470, in _compile_text 
    exec code in module.__dict__, module.__dict__ 
    File "_templates_article_mako", line 16, in <module> 
ImportError: No module named templatedefs 

現在,有趣的是,我可以直接從模板打印sys.path

<%! 
import sys 
print sys.path 
from website._webtools.templatedefs import strip_tags 
%> 

我可以確認那裏,即website的路徑。此外,進口確實在其他所有部署方案中都能正常工作。

導入websitewebsite._webtools也適用。只有website._webtools.templatedefs部分出問題了。

有沒有人有想法,我可以在哪裏找到可能出錯的跡象?

測試代碼是相當直接的:

class BuildTestCase(unittest.TestCase): 

    def setUp(self): 
     self.tmpdir = tempfile.mkdtemp() 
     self.cwd = os.getcwd() 
     os.chdir(self.tmpdir) 
     bootstrap(self.tmpdir, { # this initiates a new project 
      "URL": "localhost", 
      "TITLE": "Example", 
      "DEFAULTS": { 
       "AUTHOR": "John Doe", 
      } 
     }) 

    def test_initial_build(self): 
     """Check, if building directly after bootstrap works""" 
     build() 

    def tearDown(self): 
     os.chdir(self.cwd) 
     shutil.rmtree(self.tmpdir) 

編輯:還有一個診斷:我讓鯖模板編譯和執行所產生的Python文件獨立。奇蹟般有效。我也將templatedefs.py簡化爲最低限度(僅限於返回空字符串),以便我可以在該文件中排除ImportErrors(或其他奇怪)。

系統信息: Ubuntu 11.04,Python 2.7,Mako 0.3.6。

+0

你的'__init __。py's是什麼? – agf

+0

如果沒有看到完整的測試代碼,不完全確定有什麼問題。我注意到,如果我在testWebsite.py中導入templatedefs,那麼當構建實際運行時,我沒有導入錯誤。我懷疑os.chdir會導致你的問題。 – stderr

+0

@agf請看這裏:https://github.com/Boldewyn/website/blob/master/website/__init__.py – Boldewyn

回答

3

這的確讓人生氣。但是這裏有一些事情:

  1. ./nosetests: 這個作品和所有9個測試通過

  2. 'templatedefs'是唯一的關鍵在'_webtools.__dict__'失蹤當你添加一個'from website import _webtools'您鯖模板和比較'nosetests''python -m unittest tests.testWebsite' :其他部分早已導入

  3. sys.path包含''(相對路徑)'python -m unittest tests.testWebsite'的情況,但不在'nosetests'的情況下,其中sys.path只包含絕對路徑。這導致'website._webtools.__file__'的值不同:一個是相對['website/_webtools'],另一個是絕對['/home/username/tmp/website/_webtools']。由於您製作了os.chdir,因此相對路徑不再起作用。

SO:如果您想使用純單元測試,您可以在測試文件的開頭添加'import website._webtools.templatedefs'。這確保您在運行os.chdir時導入了模板定義。我會建議使用鼻子。希望有所幫助。

+0

是的,這有助於解決問題。感謝您的解釋!我的精神狀態得到了挽救:-) – Boldewyn