一直以为,在 python 中引用自研模块非常简单,在执行 python 命令的目录,就可直接使用目录下的文件夹名称或 python 文件名作为模块名进行引用。但在调研 kserve 项目时按上面思路却屡屡失败。
python 命令在哪个目录下执行都找不到模块名
本想把 kserve 项目下载下来直接运行 kserve sklearnserver,但总找不到模块 sklearnserver。kserve 项目地址 github.com/kserve/kserve。笔者已经把此项目下载下来,目录情况如下(笔者把本文不需要的文件删除且添加了算法模型文件夹 model)
~/kserve/python/sklearnserver/sklearnserver$ ls -ltotal 24-rw-rw-r-- 1 hello hello 730 1月 28 16:43 __init__.py-rw-rw-r-- 1 hello hello 1962 1月 31 12:19 __main__.pydrwxrwxr-x 2 ends ends 38 1月 31 16:30 model-rw-rw-r-- 1 hello hello 2609 11月 20 22:07 model.pydrwxrwxr-x 2 hello hello 147 1月 31 12:22 __pycache__-rw-rw-r-- 1 hello hello 1158 11月 7 17:32 sklearn_model_repository.py~/kserve/python/sklearnserver/sklearnserver$ pip install kserve scikit-learn joblib kserve-storage
在 sklearnserver/sklearnserver(为了表达方便没有写全路径) 目录运行报错,找不到 sklearnserver 模块。此目录下确实没有对应的 python 文件名或目录。
~/kserve/python/sklearnserver/sklearnserver$ python __main__.py --model_name sklearn-iris --http_port 9090 --model_dir ./modelTraceback (most recent call last): File "/home/hello/kserve/python/sklearnserver/sklearnserver/__main__.py", line 18, in <module> from sklearnserver import SKLearnModel, SKLearnModelRepositoryModuleNotFoundError: No module named 'sklearnserver'
到 sklearnserver/sklearnserver 的上层目录运行就可以?至少看起来在 这个目录能看到 sklearnserver 文件夹,应该就能找到模块 sklearnserver,实际运行时还是找不到。
~/kserve/python/sklearnserver$ ls -ltotal 384-rw-rw-r-- 1 1000 1000 193 Nov 7 09:32 Makefile-rw-rw-r-- 1 1000 1000 2311 Nov 7 09:32 README.md-rw-rw-r-- 1 1000 1000 1962 Jan 31 07:50 __main__.py-rw-rw-r-- 1 1000 1000 728 Jan 28 08:28 pyproject.tomldrwxrwxr-x 4 1000 1000 127 Jan 31 14:52 sklearnserver-rw-rw-r-- 1 1000 1000 373209 Jan 28 08:28 uv.lock~/kserve/python/sklearnserver$ python sklearnserver/__main__.py --model_name sklearn-iris --http_port 9090 --model_dir sklearnserver/modelTraceback (most recent call last): File "/home/hello/kserve/python/sklearnserver/sklearnserver/__main__.py", line 18, in <module> from sklearnserver import SKLearnModel, SKLearnModelRepositoryModuleNotFoundError: No module named 'sklearnserver'
让 __main__.py 打印 sys.path,看 python 运行时到底从哪些目录搜索模块。
~/kserve/python/sklearnserver/sklearnserver$ vim __main__.py。。。省略代码。。。import sysprint(sys.path)。。。省略代码。。。
从如下运行情况可知,在 sklearnserver/sklearnserver 目录执行时搜索模块路径除了系统目录就是 sklearnserver/sklearnserver,在 sklearnserver 目录执行时搜索模块路径也是除了系统目录只有sklearnserver/sklearnserver。即不管python 命令在哪里运行,sys.path 都只是添加了 __main__.py 所在的目录
~/kserve/python/sklearnserver/sklearnserver$ python __main__.py --model_name sklearn-iris --http_port 9090 --model_dir ./model['/home/hello/kserve/python/sklearnserver/sklearnserver', '/usr/local/lib/python312.zip', '/usr/local/lib/python3.12', '/usr/local/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/site-packages']。。。省略报错。。。~/kserve/python/sklearnserver$ python sklearnserver/__main__.py --model_name sklearn-iris --http_port 9090 --model_dir sklearnserver/model['/home/hello/kserve/python/sklearnserver/sklearnserver', '/usr/local/lib/python312.zip', '/usr/local/lib/python3.12', '/usr/local/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/site-packages']。。。省略报错。。。
接下来的解决方案就呼之欲出了。把__main__.py 的父目录加到 PYTHONPATH,运行时就能找到 sklearnserver 模块了。
~/kserve/python/sklearnserver/sklearnserver$ PYTHONPATH=.. python __main__.py --model_name sklearn-iris --http_port 9090 --model_dir ./model['/home/hello/kserve/python/sklearnserver/sklearnserver', '/home/hello/kserve/python/sklearnserver', '/usr/local/lib/python312.zip', '/usr/local/lib/python3.12', '/usr/local/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/site-packages']。。。省略其他输出。。。2026-02-01 02:26:59.216 248 uvicorn.error INFO: Uvicorn running on http://0.0.0.0:9090 (Press CTRL+C to quit)
也可使用 python -m sklearnserver,它要求模块名所在的目录包含 __main__.py(本例符合条件),并自动把模块名所在的目录加入模块搜索路径。