在从ipython运行时按预期将包添加到sys.path导入的脚本,但在从python运行该脚本时引发异常

在从ipython运行时按预期将包添加到sys.path导入的脚本,但在从python运行该脚本时引发异常,python,ipython,setuptools,ubuntu-14.04,Python,Ipython,Setuptools,Ubuntu 14.04,我是一个困惑的Python爱好者。我发帖子时认为我的虚拟电视有问题。更多的故障排除表明情况可能并非如此 我将非常感谢任何见解或故障排除技巧,以便我能够继续进行软件包开发。提前谢谢你 我在使用Python 2.7.6的Ubuntu 14.04.1 LTS系统上遇到的问题摘要: 我有一个名为test_dummy.py的脚本,它将包路径添加到sys.path,然后尝试导入包 当脚本在ipython的run test\u dummy.py内部运行时,包导入不会出错 当脚本使用python test\u

我是一个困惑的Python爱好者。我发帖子时认为我的虚拟电视有问题。更多的故障排除表明情况可能并非如此

我将非常感谢任何见解或故障排除技巧,以便我能够继续进行软件包开发。提前谢谢你

我在使用Python 2.7.6的Ubuntu 14.04.1 LTS系统上遇到的问题摘要:

  • 我有一个名为test_dummy.py的脚本,它将包路径添加到sys.path,然后尝试导入包
  • 当脚本在ipython
    run test\u dummy.py
    内部运行时,包导入不会出错
  • 当脚本使用
    python test\u dummy.py
    运行时,会为某些包引发ImportError异常
  • 最令人沮丧的是,包含代码的包,即不仅仅是一个
    \uuuu init\uuuuu.py
    文件,无一例外地导入。仅包含
    \uuuu init\uuuu.py
    文件的简单测试包不会按预期导入。当从python调用脚本时,我无法确定是什么导致最简单的包在导入时抛出异常,即
    python test\u dummy.py
  • 我的pwd是这样的:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    
    test_a
    ├── __init__.py
    └── __init__.pyc
    
    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    
    HELLO = 'Hello, world!'
    print HELLO
    
    tests
    └── test_dummy.py
    
    测试结果如下所示:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    
    test_a
    ├── __init__.py
    └── __init__.pyc
    
    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    
    HELLO = 'Hello, world!'
    print HELLO
    
    tests
    └── test_dummy.py
    
    你好,世界是这样的:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    
    test_a
    ├── __init__.py
    └── __init__.pyc
    
    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    
    HELLO = 'Hello, world!'
    print HELLO
    
    tests
    └── test_dummy.py
    
    hello.py是这样的:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    
    test_a
    ├── __init__.py
    └── __init__.pyc
    
    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    
    HELLO = 'Hello, world!'
    print HELLO
    
    tests
    └── test_dummy.py
    
    其他包['browser'、'display'、'singleton']都包含init.py文件和其他在运行时不会引发已知异常的代码

    测试如下:

    .
    ├── browser
    ├── display
    ├── hello_world
    ├── singleton
    ├── test_a
    └── tests
    
    test_a
    ├── __init__.py
    └── __init__.pyc
    
    hello_world/
    ├── hello.py
    ├── hello.pyc
    ├── __init__.py
    └── __init__.pyc
    
    HELLO = 'Hello, world!'
    print HELLO
    
    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测试/test\u 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
    
    加载包'/home/dmmmd/development/my\u python/browser'
    正在加载包“/home/dmmmd/development/my\u python/display”
    正在加载包“/home/dmmmd/development/my_python/singleton”
    正在加载包“/home/dmmmd/development/my\u python/test\u a”
    正在加载包“/home/dmmmd/development/my\u python/hello\u world”
    正在加载“浏览器”
    正在加载“显示”
    加载“singleton”
    加载“测试a”
    回溯(最近一次呼叫最后一次):
    文件“tests/test_dummy.py”,第46行,在
    导入lib.import_模块(项目)
    文件“/usr/lib/python2.7/importlib/_init_uuu.py”,第37行,在导入模块中
    __导入(名称)
    ImportError:没有名为test_a的模块
    
    在python解释器中导入包“test_a”不会引发异常:

    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'>
    >>>
    
    Python 2.7.6(默认,2014年3月22日,22:57:26)
    [GCC 4.8.2]关于linux2
    有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
    >>>导入系统
    >>>sys.path.append('/home/dmmmd/development/my\u python/test\u a')
    >>>进口测试
    >>>打印测试
    >>>
    
    我找到了一个解决方案,尽管该解决方案没有解决为什么在使用
    python test\u dummy.py运行脚本时,以特殊方式添加到
    sys.path
    的某些包路径不会被导入的问题

    我最初在尝试使用py.test时遇到了这个问题。关于“使用virutalenv、pip和可编辑模式管理您的项目”,我忽略了它,因为我认为它对于我的Python知识水平来说太高级了

    在读了关于“”的文章后,我决定试试这个技巧

    在pwd中,我创建了一个带有以下代码的
    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")
    
    然后,我执行了以下代码,得到了预期的结果:

    $ 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
    时才会出现故障
    ipython test_dummy.py
    在不首先安装本地软件包的情况下工作

    不过,我很高兴了解了一些关于python安装和打包的知识。
    test\u dummy.py
    脚本现在在从
    python tests/test\u dummy.py
    调用时按预期运行

    我现在不明白为什么在运行
    test\u dummy.py
    脚本时,其中三个包已经在
    sys.path
    中:

    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
    的事情,但这是可能的,因为我一直在做各种教程。它们不在我没有运行我创建的
    setup.py
    的任何其他环境中的
    sys.path

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

    谢谢大家的意见

    注意:这是一个新的virtualenv之后的
    python test\u dummy.py
    的输出:
    test\u a
    中的
    \uuuu init\uuuuuuuuuuuupy.py
    看起来如何?在
    browser
    ?browser/\uuuu init\uuuuuuuuy.py中包含一条注释,并且
    从浏览器导入Firefox
    。在test_a中,init.py是空的。我不知道是什么问题,您是否尝试向
    test_a
    添加一些代码,或者将
    browser
    文件夹名更改为
    test_a
    并查看它是否已导入?这是一个我所知不多的复杂问题。看看我贴的答案。谢谢你的帮助,t·皮门特尔。我确实尝试过更改
    test\u a
    browser
    的名称。异常仍然被抛出。