问题
我的项目有一个目录结构,该结构遵循使用此cookiecutter模板创建的Python软件包的标准: https://github.com/audreyr/cookiecutter-pypackage#quickstart
目录结构为
const express = require("express");
const cors = require("cors");
const app = express();
const server = require("http").Server(app);
const io = require("socket.io")(server);
// parse application/json [ With Express ]
app.use(express.json());
// application/x-www-form-urlencoded parser [ With Express ]
const urlencodedparser = express.urlencoded({ extended: false });
// Use Cors As Middleware
app.use(cors());
app.get("/", (req, res) => {
res.send("Hello World");
});
server.listen(8080, () => console.log("Server Started on Port 8080"));
// Connect to io Socket(s)
io.on("connection", socket => {
// Join Rooms
socket.on("join-room", room => {
console.log(room.roomName);
socket.join(room.roomName);
socket.on("send-msg", info => {
if (info.roomName === room.roomName) {
io.to(room.roomName).emit("send-msg", { msg: info.msg });
} else {
return;
}
});
});
// Leave Rooms
socket.on("leave-rooms", room => {
socket.leaveAll();
});
});
project_name
├── project_name
│ ├── __init__.py
│ └── module1.py
└── tests
└── test_module1.py
的第一行代码是:
test_module1.py
但是我得到一个from project_name import module1
。
据我所知,这应该起作用,因为名为ModuleNotFoundError: No module named 'project_name'
的文件夹是一个程序包,可以通过project_name
文件的存在来确保。
我一直很难理解这样的导入是如何工作的。对于我的项目,我一直都希望将测试与要测试的模块放在同一文件夹中。我知道这是不好的做法,但这是我可以实际导入模块的唯一方法。
我已经尝试过的东西
我尝试将带有__init__.py
文件的文件夹重命名为其他名称,然后导入,因为我认为这可能与名称均为__init__.py
的父文件夹和子文件夹有关。这没有用,同样的错误。
即使Cokkiecutter模板没有该文件夹,我也尝试通过在其中创建project_name
文件的方式将测试文件夹放入包中。
我在很多地方都读到不鼓励将测试文件夹放入程序包中,但有些人建议采用这种结构。那也不起作用。
我已经彻底搜索了这个看似非常标准的问题的解决方案,有些链接在这里:
我最后的尝试是使用Cookiecutter启动一个项目,因此从一开始就可以正确设置所有内容。但是,我仍然得到__init.py__
。
我不想要的
我不想修改ModuleNotFoundError
,因为似乎答案很多。对于这种常见问题,必须有一种更清洁的方法。
我在做什么错?
编辑一些其他信息(请参阅@Nicholas的问题):
init .py”的内容为
sys.path
这是由Cookiecutter模板生成的。
在# -*- coding: utf-8 -*-
"""Top-level package for project_name."""
__author__ = """my_name"""
__email__ = 'my_email'
__version__ = '0.1.0'
内部,我在test_module1
发生之前添加了以下内容:
ModuleNotFoundError
import sys
import os
print(sys.path)
print(os.getcwd())
打印一个列表,其中第一个元素是sys.path
目录。
tests
我不知道第一个元素中的小写字母'c'是否重要。
['c:\\Users\\...\\project_name\\tests',
'C:\\Users\\...\\Miniconda3\\python37.zip',
'C:\\Users\\...\\Miniconda3\\DLLs', 'C:\\Users\\...\\Miniconda3\\lib',
'C:\\Users\\...\\Miniconda3',
'C:\\Users\\...\\Miniconda3\\lib\\site- packages',
'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\win32',
'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\win32\\lib',
'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\Pythonwin']
打印根目录os.getcwd()
。还带有小写字母“ c”。
答案 0 :(得分:1)
您应该创建一个虚拟环境并安装项目,以使测试模块正确解析导入语句。
在项目根目录(即包含子目录project_name
和子目录project_name
的目录tests
中,创建一个setup.py
(或pyproject.toml
)文件包元数据。有关该部分的详细信息,请参见here。
从现在包含安装程序(setup.py
)的同一项目根目录中,创建并激活venv并安装您的项目:
python3 -m venv .venv
source .venv/bin/activatate # linux/macOS
# .\Scripts\activate.bat # windows
pip install --editable .
pip install pytest
pytest
如果由于某种原因您不想为您的项目创建安装程序,则可以从项目目录运行pytest,如下所示:
python3 -m pytest
与简单的pytest
命令不同,这会将当前工作目录添加到sys.path
中,从而可以在测试中解析导入语句。