外部库导入依赖项时,本地文件优先

时间:2018-08-08 17:23:23

标签: python

我有2个本地文件,strategy.pysignal.py

$ ls -1 ~/src/foo
signal.py
strategy.py

strategy.py

$ cat strategy.py
import numpy

signal.py

$ cat signal.py 
import talib

除了这些单个导入行外,两个文件都为空。

当我尝试运行strategy.py时,当numpy的一个依赖项尝试signal.py时,本地import signal优先。

$ python strategy.py 
Traceback (most recent call last):
  File "strategy.py", line 1, in <module>
    import numpy
  ...
  File "/home/steve/src/foo/.venv/lib/python3.6/site-packages/numpy/testing/__init__.py", line 10, in <module>
    from unittest import TestCase
  File "/usr/lib/python3.6/unittest/__init__.py", line 64, in <module>
    from .main import TestProgram, main
  ...
  File "/usr/lib/python3.6/unittest/signals.py", line 1, in <module>
    import signal
  File "/home/steve/src/foo/signal.py", line 1, in <module>
    import talib
  File "/home/steve/src/foo/.venv/lib/python3.6/site-packages/talib/__init__.py", line 43, in <module>
    from ._ta_lib import (
  File "__init__.pxd", line 163, in init talib._ta_lib
AttributeError: module 'numpy' has no attribute 'dtype'

如果我将本地文件重命名为其他文件,则不会发生上述错误

$ mv signal.py signal_foo.py
$ python strategy.py 
$ echo $?
0

问题:

  • 除了要求我选择唯一的文件名之外,还有什么方法可以解决此问题?
  • 如果是这样,如何确定我的文件名将来不会冲突,需要我选择另一个唯一的文件名?

注释:

我正在virtualenv内跑步,并且正在使用python-3.6.5

1 个答案:

答案 0 :(得分:4)

此行为符合Module Search Path

  

导入名为垃圾邮件的模块时,解释器首先搜索   具有该名称的内置模块。如果找不到,则进行搜索   在目录给定的目录列表中找到名为spam.py的文件   变量sys.path。 sys.path从以下位置初始化:

     

包含输入脚本的目录(或当前目录)。   PYTHONPATH(目录名称列表,语法与   shell变量PATH)。安装相关的默认值。

     

初始化后,Python程序可以修改sys.path。的   包含正在运行的脚本的目录位于开头   在标准库路径之前的搜索路径中。这表示   该目录中的脚本将被加载,而不是   库目录中的名称相同。

因此,一个答案是您可以操纵sys.path,将要使用的任何目录放在列表的第一位。但是,这并不能真正解决您的长期问题。

更好的方法是将自己的代码组织到Packages中。

  

包是一种通过使用来构造Python模块名称空间的方法   “点缀的模块名称”。例如,模块名称A.B表示一个   名为A的程序包中名为B的子模块。

如果您将signal.py放在包myPkg中,则可以使用;专门导入它。

import myPkg.signal

如果将两个信号模块都导入到同一脚本中,这可能仍不能解决所有问题。但是,您可以使用以下方式在import上分配新的模块名称:

import myPkg.signal as mySignal

在工作目录中创建此结构;

/path/to/myPkg/
    __init__.py
    signal.py
    tests/
        __init__.py
        test.py

test.py中输入类似的内容

print '1'
import signal

print '2'
import myPkg.signal as ms

现在,要运行此命令,您需要将myPkg添加到PYTHONPATH,或进行快速检查,请在解释器中进行尝试。注意:cdmyPkg的父目录,而不是myPkg

cd /path/to
python
>>> import sys
>>> sys.path
['', '/usr/lib/python27.zip', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-cygwin', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/lib/python2.7/site-packages']
>>> sys.path.append('./myPkg')
>>> import myPkg.tests.test
1
2
>>> quit()