Python 3.x 导入时出现的问题

3

我的问题可以总结如下:

我有以下文件结构:

<path>/
- a.py
<path>/subdir/
- b.py
- c.py

关系是a导入b并且b导入c(a->b->c)。
更确切地说,每个文件的内容如下:
  • c.py
def foo():
    print("Hello World!")
  • b.py
import c
def fie():
    c.foo()
    print("Second Hello World!")
if __name__=="__main__":
    fie()
  • a.py
from subdir import b
b.fie()

我希望的是,当调用a.py时,它将打印出以下字符串:

$ python3 a.py
Hello World!
Second Hello World!
$ 

并且从 /subdir 调用 b.py 将打印相同的内容:

$ cd subdir
$ python3 b.py
Hello World!
Second Hello World!
$ 

如果我从<path>调用a.py,会得到以下结果:

$ python3 a.py
Traceback (most recent call last):
  File "a.py", line 1, in <module>
    from subdir import b
  File "<path>/subdir/b.py", line 1, in <module>
    import c
ModuleNotFoundError: No module named 'c'
$ 

如果我从<path>/subdir调用b.py,就会得到预期的行为:
$ cd subdir
$ python3 b.py
Hello World!
Second Hello World!
$ 

如果我按照以下方式更改b.py:
  • b.py
from subdir import c
def fie():
    c.foo()
    print("Second Hello World!")
if __name__=="__main__":
    fie()

调用a.py的工作按预期进行,但这一次调用b.py却出现了ModuleNotFoundError错误:

$ cd subdir
$ python3 b.py
Traceback (most recent call last):
  File "b.py", line 1, in <module>
    from subdir import c
ModuleNotFoundError: No module named 'subdir'
$ 

很奇怪,即使是在 <path> 的调用中,也会出现相同的错误:

$ python3 subdir/b.py
Traceback (most recent call last):
  File "b.py", line 1, in <module>
    from subdir import c
ModuleNotFoundError: No module named 'subdir'
$ 

如果我要替换 b.py 文件中的以下字符串:
from subdir import c

from . import c

我的最新测试结果完全相同。

在实际情况下,b和c都是位于子目录中的库的一部分,该库既可以直接使用(通过if __name__ 技巧),也可以从任何其他地方导入以使用其函数。该库目前不能安装在文件系统的固定位置上(或者至少我不应该依赖它)。

在使用Python 2.6时,我从未遇到过这样的问题,而现在我正在迁移到Python 3.x。阅读Python 3.x导入指南很有帮助,但我没有找到任何有用的信息来解决这个基本的问题(这就是为什么我认为我在那里忽略了一些微不足道的东西)。

您能建议一种改变 [a,b,c] 中任何一个 .py 文件以满足这种情况的方法吗?

2个回答

0
我将我的目录结构保持如下: C:\Users\G1\Desktop\Test 目录
30-06-2019  01:17                   a.py
30-06-2019  01:17    <DIR>          path/

 Directory of C:\Users\G1\Desktop\Test\path

30-06-2019  01:18                b.py
30-06-2019  01:15                c.py

a.py

import sys
**sys.path.append("path")**
from path import b
b.fie()

b.py

import c
def fie():
    c.foo()
    print("Second Hello World!")
if __name__=="__main__":
    fie()

c.py

def foo():
    print("Hello World!")

输出:

C:\Users\G1\Desktop\Test>python a.py
Hello World!
Second Hello World!

C:\Users\G1\Desktop\Test>python path\b.py
Hello World!
Second Hello World!

你需要添加模块c.py的路径。

以上代码已在Python3和Python2中测试过。


这是我以前在Python 2.6中使用的方法。在Python 3.x中不再起作用。您能否确认在您的测试中使用的是Python 3.x? - joe345wa
1
你尝试过像上面的代码中提到的那样添加路径吗?试试看,它能正常工作,我测试过了。 - G1Rao
@joe345,你应该能够使用绝对或相对导入来让它工作,就像你之前尝试的那样。当我在b.py的顶部放置from subdir import c并运行b.py时,它可以正常工作,我没有收到ModuleNotFoundError的错误提示。我是在运行Python 3.7 Windows 10。我不确定出了什么问题... - probat
@probat,joe345wa说,b.py和c.py都应该在同一个文件夹中,然后我添加了"from path import c",但它抛出了一个异常ModuleNotFoundError: 找不到名为"path"的模块 - G1Rao
@joe345,在a.py中打印sys.path并没有显示到sub目录的路径。当然只会显示a.py的路径。 - probat
显示剩余9条评论

0
以下内容适用于我(至少在Windows下)。
通过调用addpath来启动您的主程序,将要让您的应用程序访问的目录(作为字符串)或目录列表(作为字符串列表)作为参数传递:
def addpath(dirs):
  import sys,os
  my_path = '/'.join(os.path.abspath(sys.argv[0]).replace('\\','/').split('/')[:-1])+'/'
  if type(dirs) is str:
    sys.path.append(my_path+dirs)
  elif type(dirs) is list:
    for dir in dirs:
      sys.path.append(my_path+dir)

################################################################################

addpath('subdir')  #or addpath(['subdir1',...])

from subdir import b
b.fie()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接