我是靠谱客的博主 单薄钢铁侠,最近开发中收集的这篇文章主要介绍python import什么意思_[Python] 也整理一下万恶的Python import机制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

关于Python import,基本上是个写Python的人都遇到过(除非你从来不拆分项目的目录结构)。这个问题在StackOverflow上被讨论了七八年,但其实早就有人提出过,只要模块搜索路径里包含项目根目录,这个愚蠢的问题就没了,但从来没有人正面回答过这个问题。

结果就是,万恶的import机制仍然在祸害着每一个人。

Python的import机制坑在哪?

假设项目目录是这样子的——

import_test

|_______ modules

| |____ __init__.py

| |____ a.py

| |____ b.py

|_______ tests

| |____ __init__.py

| |____ test_a.py

| |____ test_b.py

|_______ app.py

app.py假设是你的主程序,从这里运行的时候,import是不太容易出问题的,绝对路径也好相对路径也好。坑在tests这个目录,把测试脚本放到一个目录里这本身没问题,但是,如果你在tests下直接运行这些测试脚本,你就会踩坑。

比如,test_a.py从modules里导入了a,如下所示——

from modules import a

a = a.a1()

if a > 50:

print(a)

else:

print(100-a)

当你运行的时候,你会发现Python找不到modules在哪 ,这是自然的,因为模块搜索路径里没有包含上级目录,所以会报错ModuleNotFoundError: No module named 'modules'

import_test> python tests/test_a.py

Traceback (most recent call last):

File "tests/test_a.py", line 1, in

from modules import a

ModuleNotFoundError: No module named 'modules'

import_test>

有人说-m这个参数有效,我试过,仍然是要退回到import_test这个目录,而且要注意,不能加.py,因为此时你运行的是一个模块,如下所示——

import_test> python -m tests.test_a

100

import_test>

Pycharm的优化可能会让你更懵逼

其次,如果你用pycharm,你可能会直到上线的那天你才发现这个问题,因为pycharm非常人性化,它自动帮你把项目路径添加好了,所以在pycharm里,你是可以直接在tests下 执行test_a.py的 ,不会有任何问题。差别很容易找到,在代码最前面加上这么两行,然后分别在pycharm和其它IDE,比如vscode里执行——

import sys

print(sys.path)

你会发现pycharm里打出来的路径是更多的,它把项目根目录加进去了。如果你在不知情的情况下继续开发下去,并且你把需要直接执行的代码,放在了类似于tests这样的目录下面,而不是import_test这个根目录下,等你上线代码那天,你就有的哭了,你会看到各种导入失败的错误,而你平时用pycharm却毫无感觉……

也许这才是真正科学的做法——把测试case写成模块,而不是脚本

我因为最初用的vscode,在import这个问题上纠结了无数次……然而python的import就是这么反人类,我又不想把测试脚本全都扔到最外面,后来我发现很多项目是把测试的case写在tests目录下,然后在外面留一个入口脚本去导入这些测试case,说白了,测试case本身也变成了一个模块,测试目录变成了一个包。

参考

最后贴两篇有用的参考,第二篇是一位台湾老师写的

我摘出其中最关键的解释

# 標準的 explicit relative import 寫法

from .sample_module import sample_func

1. 包含相對路徑的檔案不能直接執行,只能作為 module 被引用,所以失敗

2. 成功印出 Hello!

相对引用是有限制的,比如tests目录下的模块是没办法通过相对引用,直接引用到modules下面去的

以我们的例子来看

from .a import a1

a = a1()

if a > 50:

print(a)

else:

print(100-a)

这个运行的结果将会是一个错误

import_test> python -m tests.test_a

Traceback (most recent call last):

……

ModuleNotFoundError: No module named 'tests.a'

import_test>

所以,我个人跨包导入的时候,都是用的绝对导入

# 標準的 absolute import 寫法

from sample_package.sample_module import sample_func

1. 如果此層目錄位置不在 python path 中,就會失敗

2. 成功印出 Hello!

也就是

from modules import a

a = a.a1()

if a > 50:

print(a)

else:

print(100-a)

小结

贴一个stackoverflow的连接,在这个连接里,被采纳的回答在7年后更新了答案,所以你就知道这个问题真的是个老问题了……

一个更加广为人知的做法是sys.path.append,但就像很多在stackoverflow上提问的人说的那样,我个人一点也不喜欢这种做法,也许只是用在测试脚本里没有问题,但它看上去更奇怪

另外,这个链接里也有一段有意思的内容——

换言之,Python的开发团队是知道这个问题也讨论过的,所以,真傲慢。

The only use case?

最后

以上就是单薄钢铁侠为你收集整理的python import什么意思_[Python] 也整理一下万恶的Python import机制的全部内容,希望文章能够帮你解决python import什么意思_[Python] 也整理一下万恶的Python import机制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部