【python】常见问题——项目在pycharm能运行,命令行运行报错

原因

  • 从命令行运行python的时候,系统会自动将运行文件的文件夹路径添加到系统的path变量中,例如:

    在E:\Dat\Golden_Data\testcase\test1.py文件中写入如下代码并运行
    import sys
    print(sys.path)
    

    得到的结果为:

    image-20200806135308735

    其中打印出来的E:\\Dat\\Golden_Data\\testcase就是运行的test1.py文件所在的文件夹路径

  • pycharm中运行项目的时候,会默认将当前项目的根目录也加入到path变量中,这样在pycharm写导入文件路径的时候,就可以从项目根目录开始写而不会报错,例如:

    在E:\Dat\Golden_Data\testcase\test1.py文件使用pycharm的run命令运行刚才的代码
    import sys
    print(sys.path)
    

    得到的结果为:

    image-20200806151001083

    其中打印出来的E:\\Dat\\Golden_Data\\testcase依旧是运行的test1.py文件所在的文件夹路径,后面新增加的E:\\Dat\\Golden_Data就是当前项目的根目录路径了,这个是pycharm自动添加的。

  • 因为pycharm和命令行之间的对于path变量的不同,导致如果在pycharm编辑器中根据智能提示添加的导入或者手动编写的根据项目根目录写的路径,在命令行中运行时就会报文件、模块找不到的错误

解决思路

  • 因为两者之间差距就是项目根目录,那么可以在入口文件中将项目根目录添加到path变量中,就可以解决这些问题了。

解决方案一:

  • 在项目根目录下建立一个文件夹tools,文件夹中建立一个py文件,写一个方法从该文件获取项目根目录的绝对路径,因为此文件相对于项目根目录的路径是固定的,所以可以利用python的os库方法来根据层级获取到根目录路径,代码如下:

    def get_root_dir():
        return os.path.dirname(os.path.dirname(__file__))
    
    # 其中的__file__表示当前文件的存储路径
    # os.path.dirname表示获取参数中路径的目录部分
    # 利用两次dirname方法,可以获取当前文件目录的上级目录绝对路径,因为当前文件相对于项目根目录的位置为两层,所以这样获取到的绝对路径结果就是项目根目录的绝对路径
    
  • 能够获取项目根目录的绝对路径之后,只需要在项目的入口文件,也就是命令行中运行的py文件初始添加代码,将这个路径加入到path变量中,就能让项目中的导入语句跟在pycharm里执行一样,不报错了

    import sys
    sys.path.append(get_root_dir())
    # 将这两句添加到入口文件的起始位置,这样之后的导入和其他文件的导入就不会报找不到的问题了
    
  • 当然 解决方法很多,欢迎大家提出自己的解决方案,找到一个最优雅的解决方案

解决方案二:

  • 之前提出的方法发现一个问题,因为入口文件位置不确定,可能会导致导入get_root_dir方法时报错,陷入一个想要解决导入问题,要先解决导入解决问题的文件的问题的尴尬局面。。。

  • 可以考虑改用以下方法,需要自己修改一下参数,但是不会有之前的提取导入问题

    import os, sys
    path = os.path.abspath(__file__)
    for i in range(x):
      path = os.path.dirname(path)
      sys.path.append(path)
    

    其中range(x)中的x是当前入口文件相对项目根目录的层级数量,比如目录结构为:

    image-20200807161442401
    当入口文件处于sample文件夹下时,默认path中添加的目录为c:\PycharmProjects\\pythonbook\\tools\\sample 这种情况下当前文件相对于根目录的层级为2层,那么x就写为2,将这段代码放在程序的入口文件开头位置,这样项目文件中在pycharm生成的导入目录就能正常生效了。

解决方案三

  • 在命令行运行前,将项目根目录设置到环境变量PATHONPATH中,这样python运行时会将它自动添加到sys.path内作为项目根目录,减少代码中不优雅的情况。
  • Linux/Mac: PATHONPATH=/xxx/yyy python3 xxxx.py
  • Windows:
PATHONPATH=c:\xxx\yyy
python3 xxxx.py`
2 个赞

需要先检查包内是否有__init__.py文件,如果没有这个文件python则认为是一个文件夹而不是包