最近跑rt-detr代码,修改了源码部分内容,实现了继续上次的epoch训练的功能(以训练100个epoch,继续100个epoch训练,共训练300个epoch),然后自定义了my_train.py训练脚本,使用pycharm右上角运行按钮直接运行如下:
可以看到运行成功了,训练参数epoch也为新设置的300,并且训练轮数继续从100轮到101轮开始,因为要在服务器上运行,所以尝试用python指令运行my_train.py文件如下:
可以看到运行失败了,而且训练参数的epoch明明已经设置为300了,运行时显示的却是100。
明明代码已经修改过了,为什么用python指令运行结果不一样?这个问题我网上搜了很多,可能一开始方向就没找对,看了很多说看看服务器文件和本地有没有同步、环境是否相同…
确认都没有问题后走投无路,闲鱼上找了个远程调代码的,搞了半天也没解决。😭于是就先放弃了,从头训练从1开始。
今天我又看这个问题,从pycharm运行配置出发,看看到底是哪个配置导致运行结果和使用python指令不同。然后我就一个一个配置试,就注意到了这个:Add content roots to PYTHONPATH
当我去掉这个配置的时候,使用pycharm运行结果就报和指令一样的错误了,加上就没问题了。
初步断定影响运行结果不同原因就是这个配置。
那么如何用python指令实现pycharm运行一样的效果呢?
GPT问了一下,找到了解决方法:
在运行脚本之前,将 Content Root 路径添加到环境变量
PYTHONPATH
。这里我选择临时设置,每次运行代码前都要加上PYTHONPATH该配置:
PYTHONPATH=/path/to/your/project python your_script.py
这个PYTHONPATH的路径为你这个项目的总路径
于是我将运行指令改为:PYTHONPATH=/root/rt-detr python /root/rt-detr/my_utils/my_train.py
就成功了:
我也问了一下原因(这个PYTHONPATH=/path/to/your/project python your_script.py加和不加运行有什么区别),GPT回答:
在 Linux 环境下运行以下两种方式的区别主要体现在 模块导入路径的不同:
# 方式 1:设置 PYTHONPATH 后运行 PYTHONPATH=/path/to/your/project python your_script.py # 方式 2:直接运行 python your_script.py
区别分析
PYTHONPATH
的作用
PYTHONPATH
是一个环境变量,用于指定 Python 在搜索模块和包时额外添加的路径。它会被添加到sys.path
的开头,影响 Python 的模块搜索顺序。
- 方式 1:
/path/to/your/project
会作为优先路径添加到sys.path
的开头。- 方式 2:没有修改
PYTHONPATH
,Python 仅从默认的搜索路径(如当前目录、标准库、虚拟环境中的包)中寻找模块。运行结果差异
当脚本依赖项目的模块或包时:
方式 1:如果 your_script.py中需要导入 /path/to/your/project下的模块或包,设置了PYTHONPATH后可以成功导入:
# your_script.py from my_module import some_function # my_module 在 /path/to/your/project 下
方式 2:没有设置PYTHONPATH ,如果/path/to/your/project不在默认的sys.path中,导入会失败,抛出ModuleNotFoundError。
ModuleNotFoundError: No module named 'my_module'
当脚本没有依赖额外路径时:
- 两种方式运行结果一致,
PYTHONPATH
的设置不会对脚本产生额外影响。
sys.path
的变化 可以通过打印sys.path
观察路径的差异:import sys print(sys.path)
方式 1(设置了
PYTHONPATH
):/path/to/your/project
会被添加到sys.path
的开头。例如:['/path/to/your/project', '/usr/lib/python3.9', ...]
方式 2(未设置
PYTHONPATH
):/path/to/your/project
不会出现在sys.path
中:['/current/working/directory', '/usr/lib/python3.9', ...]
模块冲突的优先级问题
如果存在模块名冲突,例如:
- 一个名为
my_module
的模块同时存在于/path/to/your/project
和默认路径中(如/usr/lib/python3.x
)。- 方式 1 会优先加载
/path/to/your/project/my_module
。- 方式 2 会加载默认路径下的
my_module
。总结:加和不加的区别
- 加
PYTHONPATH
:
- 添加自定义路径到模块搜索路径,适用于需要导入项目中特定路径的模块或包的场景。
- 会改变
sys.path
,可能影响模块的加载顺序。- 不加
PYTHONPATH
:
- 使用默认的模块搜索路径,适合独立脚本或完全依赖标准库和虚拟环境的项目。
- 如果脚本依赖特定的路径模块导入,则会失败。
所以可以这样理解:
- 使用
PYTHONPATH
:
项目结构复杂,代码分散在多个路径中,并且需要动态添加路径到模块搜索范围。 - 不使用
PYTHONPATH
:
项目依赖完全被虚拟环境管理,或代码与脚本在同一目录中,直接运行即可。
啰嗦这么多,就是在python指令前加个PYTHONPATH就行了。
补充一点,一般服务器训练都是后台训练,会用到nohup指令,如果使用nohup的话指令该这样写:
使用 env
显式指定环境变量,将环境变量通过 env
设置:
nohup env PYTHONPATH=/root/rt-detr python /root/rt-detr/my_utils/my_train.py > train_urpc_siou_resume.log 2>&1 &