我是编程新手,正在练习爬虫项目,Python 到底如何导入包?
xxx_project
├── README
└── app
├── models.py
├── main.py
└── crawler
└── scraper_1.py
└── scraper_2.py
└── scraper_3.py
models 定义了数据库引擎和会话,我想让 scraper 能够与数据库交互,但是
from ..models import func
会得到报错
ImportError: attempted relative import with no known parent package
而
from app.models import func
又会得到报错
ModuleNotFoundError: No module named 'app'
网上提到的在 app 目录下创建空白 __init__.py
似乎也没有效果,而 GPT 提到的将 app 目录添加到环境变量是最佳做法吗?还是说我这样的目录结构本身就是错的?
1
mickerwx 87 天前 1
把你原来的导入删掉 然后在 scraper 里面写上 models 的模型名称,这个时候模型名称会报错,你把鼠标放上去,下面就会出现 import.... 点击一下 就可以了 前提你用的是 pycharm
|
2
yanghanlin 87 天前 via Android 1
试试 python -m app.main 而非 python app/main.py 呢
|
3
ztm0929 OP @yanghanlin hhh 忘记说了,同目录下的 main 是可以导入 models 并成功识别的,不过-m 选项确实网上也有提到,我再试试看
|
5
NoOneNoBody 87 天前 1
给个我自用的方案,但我没编译过,不知道编译时会否出错
在项目每个有 py 的子目录,都放一个空的,0 字节的 __init__.py ,项目根目录不需要 然后,所有 import 都写为 from 一级子目录.二级子目录.xxx import ...,即使是内层的 py 也是这样写,总之就是从第一级开始写 例如你这个,app 视为项目根目录,scraper_1.py 里面 import scraper_2 ,就要写成 from crawler import scraper_2 ,或者 import crawler.scraper_2 as ...,就是不要理会在哪一级或者是否同级,都要从第一级开始写 namespace 然后,所有入口程序都应该放在项目根目录,你这个就是 app 这个目录。如果你想直接运行 scraper_1.py ,也要在 app 内另写一个 run_scraper_1.py 把 scraper_1 导入来运行 |
6
darksword21 87 天前 via iPhone 1
官方文档 package and module
|
7
assassing 87 天前 1
你需要在 app/__init__.py 中手动打入文件中的函数,例如:from .models.py import func ,注意文件名前面的点。然后在 scraper_1.py 中就能直接导入了:from app import func
|
8
cnt2ex 87 天前 2
python 会把被执行的脚本所在的目录插入到 sys.path 中,所以 import 都是相对于脚本所在位置计算的,所以一般入口脚本都是在项目根目录,其他东西都是相对于项目根目录。
如果你不想把入口脚本放在根目录,就利用 PYTHONPATH ,在里面加上项目根目录。 比如 PYTHONPATH=/whatever/comes/before/xxx_project/app python main.py 这样你的 import 都可以写成 ``` from models import something from crawler.scrapper_1 import something ``` 而不管 main.py 在哪个位置 |
9
forQ 87 天前 1
sys.path.append()
或 sys.path.insert() |
10
chenqh 87 天前 1
你把 main 移到 app 同层,就可以 from app.models import func
|
12
Sawyerhou 87 天前 1
楼上几层的观点+1 ,
现有目录结构可以试试 from models import func 如果想从 app 导入,就要 append 路径到 sys , 不然 main 函数找不到 app |
13
y1y1 87 天前 1
import 的根目录是入口文件的
|
14
kanchi240 87 天前 1
https://docs.python.org/3/tutorial/modules.html#intra-package-references
Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports. |
15
sujin190 87 天前 via Android 1
有__init__.py 文件的文件夹才是 python 的 package ,否则就是一个普通文件夹,而且如果你的 scraper 是个包含 main 的执行程序,此时是不能导入 models 的,因为不在 package 导入路径里,python import 的是 package 不是目录或者文件
|
16
EndlessMemory 87 天前 1
添加当前路径到环境变量
|
17
houzhiqiang 87 天前
根本原因是你要找到你的程序入口
|
18
houzhiqiang 87 天前 1
run.py # from app import run_app
|----app |----models.py |----__init__.py # def run_app |----crawler |---- a.py # from ..models import func $ python run.py 和 |----app |----__main__.py # from . import run_app |----__init__.py # def run_app |----models.py |----crawler |----a.py # from ..models import func $ python -m app |
19
Maerd 87 天前
楼上的很多都没说到点上,如果你是 pycharm ,可以不用配置,如果你是 vscode,需要将 PYTHONPATH 设为源代码根目录
|
20
houzhiqiang 86 天前 1
|
22
volvo007 86 天前
看看这个有没有帮助 https://www.bilibili.com/video/BV1K24y1k7XA/? spm_id_from=333.999.0.0&vd_source=bcfa969247c2baeec790cdac234b36e6
|
23
marvyn 85 天前
在对应环境的 site-packages 下新增一个 app.pth ,里面内容就是一行
比如 D:\xxx_project\app 导入时: from app.models import func |