自定义模块导入问题

时间:2017-01-04 16:57:30

标签: python

我似乎无法导入我自己的自定义NYT模块。我的项目结构如下,我在Mac上:

articulation/
    articulation/
        __init__.py # empty
        lib/
            nyt.py
            __init__.py # empty
        tests/
            test_nyt.py
            __init__.py # empty

当我尝试从第一个父目录运行python articulation/tests/test_nyt.py时,我得到了

  File "articulation/tests/test_nyt.py", line 5, in <module>
    from articulation.lib.nyt import NYT
    ImportError: No module named articulation.lib.nyt

我也试过

(venv) Ericas-MacBook-Pro:articulation edohring$ Python -m articulation/tests/test_nyt.py 
/Users/edohring/Desktop/articulation/venv/bin/Python: Import by filename is not supported.

test_nyt.py

import sys
sys.path.insert(0, '../../')
import unittest
#from mock import patch
# TODO: store example as fixture and complete test

from articulation.lib.nyt import NYT

class TestNYT(unittest.TestCase):
    @patch('articulation.lib.nyt.NYT.fetch')
    def test_nyt(self):
        print "hi"
        #assert issubclass(NYT, Article)
        # self.assertTrue(sour_surprise.title == '')"""


nyt.py

        from __future__ import division

import regex as re
import string
import urllib2
from collections import Counter

from bs4 import BeautifulSoup
from cookielib import CookieJar

PARSER_TYPE = 'html.parser'


class NYT:
    def __init__(self, title, url):
        self.url = url
        self.title = title
        self.words = get_words(url)


def get_words(url):
    cj = CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    p = opener.open(url)
    soup = BeautifulSoup(p.read(), PARSER_TYPE)
    # title = soup.html.head.title.string
    letters = soup.find_all('p', class_='story-body-text story-content')
    if len(letters)==0:
        letters = soup.find_all('p', class_='paragraph--story')
    if len(letters)==0:
        letters = soup.find_all('p', class_='story-body-text', )
    words = Counter()
    for element in letters:
        a = element.get_text().split()
        for c in a:
            c = ''.join(ch for ch in c if c.isalpha())
            c = c.lower()
            if len(c) > 0: 
                words[c] += 1
    return words



def test_nyt():
    china_apple_stores = NYT('title_test', 'http://www.nytimes.com/2016/12/29/technology/iphone-china-apple-stores.html?_r=0')
    assert(len(china_apple_stores.words) > 0)
    # print china_apple_stores.words
    fri_brief = NYT('Russia, Syria, 2017: Your Friday Briefing', 'http://www.nytimes.com/2016/12/30/briefing/us-briefing-russia-syria-2017.html')
    assert(fri_brief.title == 'Russia, Syria, 2017: Your Friday Briefing')
    assert(fri_brief.url == 'http://www.nytimes.com/2016/12/30/briefing/us-briefing-russia-syria-2017.html')
    assert(len(fri_brief.words) > 0)
    vet = NYT('title_test', 'http://lens.blogs.nytimes.com/2017/01/03/a-love-story-and-twins-for-a-combat-veteran-amputee/')
    assert(len(vet.words)>0)
    print "All NYT Tests Passed"




#test_nyt()

我尝试过以下操作,似乎没有工作 - 有谁知道如何解决这个问题? - Adding an init.py file to the top directory - &gt;没有帮助 - Entering Memory Python无法找到这个 - 也许是因为我使用的是Python 2.如果这是问题,我可以发布更多我尝试过的内容。 - 在下面的建议

的顶部添加sys.path

1 个答案:

答案 0 :(得分:0)

这样做:

import sys
sys.path.insert(0, '../../')

通常是一个坏主意。有时它对你测试某些东西很有用,或者你有一个单一用途的程序,你只需要在短时间内工作然后你就会扔掉,但总的来说这是一个坏习惯,因为一旦您移动目录或将代码提供给其他人,它可能会停止工作。我建议你不要让自己养成这样做的习惯。

您遇到此类错误的最可能原因是目录/Users/edohring/Desktop/articulation未出现在sys.path中。要做的第一件事是看sys.path中究竟是什么,一个好方法就是暂时将这些行放在test_nyt.py的顶部:

import os.path, sys
for p in sys.path:
    print(p)
    if not os.path.isabs(p):
        print('  (absolute: {})'.format(os.path.abspath(p)))
sys.exit()

然后运行

python articulation/tests/test_nyt.py

并查看输出。您将获得Python查找其模块的每个目录路径的一行,如果这些路径中的任何一个是相对的,它还将打印出相应的绝对路径,以便不会产生混淆。我怀疑你会发现/Users/edohring/Desktop/articulation没有出现在这个列表的任何地方。

如果事实证明是这样的话,那么最简单(但最不适合未来)的方法就是运行

export PYTHONPATH=".:$PYTHONPATH"
在使用Python本身使用您的模块执行任何操作之前,在shell中(不是在Python中)

。在Python启动时,PYTHONPATH环境变量中命名的目录将添加到sys.path。这只是一个临时修复,除非你将它放在像$HOME/.bashrc这样的文件中,每次打开终端窗口时shell都会读取它。您可以阅读此内容和better ways to add the proper directory to sys.path in this question

运行脚本的更好方法可能是使用shell命令

python -m articulation.tests.test_nyt

这需要在目录/Users/edohring/Desktop/articulation中运行,或者至少该目录需要出现在sys.path中才能使命令生效。但是以这种方式使用-m开关会导致Python以不同的方式处理它sys.path的设置方式,它可能适合您。您可以阅读有关how sys.path is populated in this answer的更多信息。