从ipython运行时按预期将包添加到sys.path导入的脚本,但是当从python运行脚本时抛出异常

时间:2014-09-01 13:04:37

标签: python ipython setuptools ubuntu-14.04

我是一个困惑的Python爱好者。我发布What else can I do to troubleshoot a package not importing in python yet imports in ipython while in a virtualenv?认为我的virtualenv有问题。更多的故障排除显示可能并非如此。

我很感激任何见解或疑难解答提示,以便我可以继续开发包。提前谢谢!

使用Python 2.7.6在Ubuntu 14.04.1 LTS系统上解决我的问题。:

  1. 我有一个名为test_dummy.py的脚本,它将包路径添加到sys.path,然后尝试导入包。
  2. 当脚本在 ipython 中使用run test_dummy.py运行时,包导入时没有错误。
  3. 当脚本与python test_dummy.py一起运行时,某些包会引发ImportError异常。
  4. 最令人沮丧的是,包含代码的包,即不仅仅是__init__.py文件导入,无例外。仅包含__init__.py文件的简单测试包不会按预期导入。当从python调用脚本时,我无法确定是什么导致最简单的包在导入时抛出异常,即python test_dummy.py
  5. 我的pwd是这样的:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    

    test_a就是这样:

    test_a
    ├── __init__.py
    └── __init__.pyc
    

    hello_world是这样的:

    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    

    hello.py就是这样:

    HELLO = 'Hello, world!'
    print HELLO
    

    其他软件包['浏览器','显示','单例']都包含 init .py文件和其他代码在运行时不会抛出任何已知异常。

    测试就是这样:

    tests
    └── test_dummy.py
    

    test_dummy.py中的代码:

    import importlib
    import os
    import sys
    HOME = os.path.expanduser('~')
    PYTHON = os.path.join(HOME, 'development/my_python')
    PACKAGES = [
        'browser',
        'display',
        'singleton',
        'test_a',
        'hello_world',
    ]
    MODULES = [
        '',
        '',
        '',
        '',
        'hello',
    ]
    IMPORTS = ['.'.join((pkg, module)).strip('.')
               for pkg, module
               in zip(PACKAGES, MODULES)]
    """
    append sys.path with PACKAGES if package exists and not already
    in the sys.path
    """
    for package in PACKAGES:
        package = os.path.join(PYTHON, package)
        if os.path.exists(package) is True:
            if package not in sys.path:
                print "loading package '{0}'".format(package)
                sys.path.append(package)
            else:
                print "package '{0}' already in sys.path".format(package)
        else:
            message = "Package '{0}' does not exist.".format(package)
            raise IOError(message)
    """
    import IMPORTS if the package is in sys.path
    """
    for item in IMPORTS:
        pkg_in_path = [pkg == os.path.basename(path)
                       for pkg in PACKAGES for path in sys.path]
        if any(pkg_in_path):
            print "loading '{0}'".format(item)
            importlib.import_module(item)
        else:
            raise AttributeError("{0} not in sys.path".format(item))
    

    ipython 结果:

    $ ipython
    # result
    Python 2.7.6 (default, Mar 22 2014, 22:57:26)
    Type "copyright", "credits" or "license" for more information.
    
    IPython 2.2.0 -- An enhanced Interactive Python.
    ?         -> Introduction and overview of IPython's features.
    %quickref -> Quick reference.
    help      -> Python's own help system.
    object?   -> Details about 'object', use 'object??' for extra details.
    Warning: disable autoreload in ipython_config.py to improve performance.
    
    In [3]: run tests/test_dummy.py
    loading package '/home/dmmmd/development/my_python/browser'
    loading package '/home/dmmmd/development/my_python/display'
    loading package '/home/dmmmd/development/my_python/singleton'
    loading package '/home/dmmmd/development/my_python/test_a'
    loading package '/home/dmmmd/development/my_python/hello_world'
    loading 'browser'
    loading 'display'
    loading 'singleton'
    loading 'test_a'
    loading 'hello_world.hello'
    Hello, world!
    

    来自python tests/test_dummy.py

    的结果
    loading package '/home/dmmmd/development/my_python/browser'
    loading package '/home/dmmmd/development/my_python/display'
    loading package '/home/dmmmd/development/my_python/singleton'
    loading package '/home/dmmmd/development/my_python/test_a'
    loading package '/home/dmmmd/development/my_python/hello_world'
    loading 'browser'
    loading 'display'
    loading 'singleton'
    loading 'test_a'
    Traceback (most recent call last):
      File "tests/test_dummy.py", line 46, in <module>
        importlib.import_module(item)
      File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
    ImportError: No module named test_a
    

    导入包&#39; test_a&#39;在python解释器中不会抛出异常:

    Python 2.7.6 (default, Mar 22 2014, 22:57:26)
    [GCC 4.8.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> sys.path.append('/home/dmmmd/development/my_python/test_a')
    >>> import test_a
    >>> print test_a
    <module 'test_a' from 'test_a/__init__.pyc'>
    >>>
    

1 个答案:

答案 0 :(得分:1)

虽然解决方案无法解决为什么在使用{{ 1}}。

我在尝试使用py.test时遇到了这个问题。 In the py.test documentation I saw this tip关于&#34;使用virutalenv,pip和editable模式管理您的项目。&#34;我忽略了它,因为我认为它对我的Python知识水平来说太高级了。

我决定在阅读&#34; creating your own python project之后尝试提示。&#34;

在pwd中,我创建了一个sys.path文件,其中包含以下代码:

python test_dummy.py

然后我在命令行执行以下代码:

setup.py

然后我用预期的结果执行了以下代码:

from setuptools import setup, find_packages

setup(name='import_troubleshooting', version='1.0')
packages = find_packages(exclude=[
    'my_django',
    'fake*',
    'tests*'
])

这些都没有向我解释为什么在没有先使用pip install -e . # the pip way (which just calls "setup.py develop") 安装我的软件包的情况下,无法以 ad hoc 方式添加软件包路径。奇怪的是,只有在将脚本传递给$ python tests/test_dummy.py # output package '/home/dmmmd/development/my_python/browser' already in sys.path package '/home/dmmmd/development/my_python/display' already in sys.path package '/home/dmmmd/development/my_python/singleton' already in sys.path loading package '/home/dmmmd/development/my_python/test_a' loading package '/home/dmmmd/development/my_python/hello_world' loading 'browser' loading 'display' loading 'singleton' loading 'test_a' loading 'hello_world.hello' Hello, world! 时才会失败。 pip install -e .无需先安装我的本地软件包就可以

然而,我很高兴能够学到有关python安装和打包的知识。从python调用时,ipython test_dummy.py脚本现在按预期运行。

我现在很困惑为什么在运行test_dummy.py脚本时,有三个软件包已经在python tests/test_dummy.py中了:

sys.path

我不记得做任何会将这些内容添加到test_dummy.py的内容,但这是可能的,因为我一直在做各种教程。在我没有运行我创建的package '/home/dmmmd/development/my_python/browser' already in sys.path package '/home/dmmmd/development/my_python/display' already in sys.path package '/home/dmmmd/development/my_python/singleton' already in sys.path 的任何其他环境中,它们不在sys.path中。

我的困惑是Python复杂性的一个症状,而不是原因!

感谢大家的投入。

注意:这是一个新的virtualenv之后sys.path的输出:

setup.py