纺织服装网站建设规划方案,环境设计公司排名,运营派网站,企业云app下载1.pycharm运行python脚本的过程
使用pycharm等编辑器run/debug运行python脚本时#xff0c;编辑器会通过本地python命令全路径执行脚本#xff0c;例如
D:\DevelopTools\Python\python.exe D:/Codes/一长串路径/bbss_nature_python/demo/test_no_param_in.py
并且会在pyth…1.pycharm运行python脚本的过程
使用pycharm等编辑器run/debug运行python脚本时编辑器会通过本地python命令全路径执行脚本例如
D:\DevelopTools\Python\python.exe D:/Codes/一长串路径/bbss_nature_python/demo/test_no_param_in.py
并且会在python系统环境命令路径prepend即append first拼接启动脚本的绝对目录路径和脚本依赖的绝对目录路径例如
print (sys.path)
[D:\\Codes\\一长串路径\\bbss_nature_python\\demo, D:\\Codes\\一长串路径\\bbss_nature_python, ...]
这是由于pycharm编辑器run/debug配置中自动定义了全路径工作目录、全路径启动脚本、环境命令拼接等如下图 2.python命令运行python脚本常见模块引入问题
例1
D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_custpython bbss_nature_python/demo/test_no_param_in.py
在以上工作目录使用相对路径运行python脚本报错如下(绝对路径也是同样的报错)Traceback (most recent call last): File D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py, line 17, in module from common_code import ScriptReturnClz, _object2json_strModuleNotFoundError: No module named common_code 例2
D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_custpython bbss_nature_python/demo/test_no_param_in.py
在以上工作目录使用相对路径运行python脚本报错如下(绝对路径也是同样的报错)Traceback (most recent call last): File D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py, line 18, in module from ..common_code import ScriptReturnClz, _object2json_strImportError: attempted relative import with no known parent package 3.python命令运行python脚本模块引入问题的解决方案
Python在引用库文件时会自动从python安装目录的Lib子目录等目录查找依赖默认查找路径可以通过命令print(sys.path)查看
print (sys.path)[D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python\\demo, D:\\DevelopTools\\Python\\python310.zip, D:\\DevelopTools\\Python\\DLLs, D:\\DevelopTools\\Python\\lib, D:\\DevelopTools\\Python, D:\\DevelopTools\\Python\\lib\\site-packages]
可以看到python命令执行一个python脚本前会在sys.path数组第一位拼接启动脚本的目录绝对路径
测试用例目录文件树形图如下 3.1模块和当前脚本在同一目录下
在引用自定义模块时如果模块和当前脚本在同一目录下引入的时候有以下几种方式
1.直接模块名引入√【不建议】
如
from test_with_param_in import _print_json_param
此时pycharm编辑器会告警但python、pycharm运行都是正常的
可以选择忽略告警(告警右键选择ignore) 2.包名.模块名引入√【推荐参见后文最佳方案】
如
from demo.test_with_param_in import _print_json_param
此时pycharm编辑器不会告警但python运行会报错
Traceback (most recent call last): File D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py, line 16, in module from demo.test_with_param_in import _print_json_param
ModuleNotFoundError: No module named demo
此时需要引入缺少的模块所在的目录的绝对路径如下
current_script_dir os.path.split(os.path.realpath(__file__))[0]
current_script_dir_parent os.path.split(current_script_dir)[0]
sys.path.insert(0, current_script_dir_parent) 3..模块名引入×【不可行】
如
from .test_with_param_in import _print_json_param
此时pycharm编辑器不会告警但python运行会报错
Traceback (most recent call last): File D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py, line 16, in module from .test_with_param_in import _print_json_param
ImportError: attempted relative import with no known parent package
无解决方案
3.2模块和当前脚本在不同目录下
如果模块和当前脚本不在同一目录下必须指定模块路径可以在当前脚本中import sys然后
通过sys.path.append(‘待引入的模块路径’)或者sys.path.insert(0,‘待引入的模块路径’)拼接的方式加入python系统命令路径建议insert
待引入的模块路径应该使用绝对(abs)路径对于相对路径python会直接拼接工作目录相对路径生成绝对路径拼接后的绝对路径是错误的(除非工作目录本身就是启动脚本的目录)
脚本内容
# 当前脚本abs目录
current_script_dir os.path.split(os.path.realpath(__file__))[0]
# 当前脚本目录的上级abs目录(对于本测试用例即为待引入模块的abs目录)
current_script_dir_parent os.path.split(current_script_dir)[0]
# 待引入模块common_code的abs目录加入系统环境命令路径数组sys.path.insert(0, current_script_dir_parent)
print(print (\sys.path\))
print(sys.path)# 引入自定义模块common_code【注意代码中必须先添加路径之后才能引入】from common_code import ScriptReturnClz, _object2json_str 命令 D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_custpython bbss_nature_python/demo/test_no_param_in.py 运行结果
print (sys.path)[D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python, D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python\\demo, D:\\DevelopTools\\Python\\python310.zip, D:\\DevelopTools\\Python\\DLLs, D:\\DevelopTools\\Python\\lib, D:\\DevelopTools\\Python, D:\\DevelopTools\\Python\\lib\\site-packages]
4.python命令运行python脚本模块引入的最佳方案
4.1复杂工程的依赖遍历问题
当待引入的模块和当前脚本在不同目录下时需要在环境变量中加入待引入模块目录的绝对路径每个类似的启动脚本(即python命令执行的脚本)都需要编写很多类似的模板代码而且由于依赖的传递性可能无法简单地遍历出所有的自定义依赖模块
4.2 IDE的依赖默认引入方式
复杂依赖的python脚本尤其是系统级规模化的python工程通常使用pycharm等IDE编写。IDE会创建python工程并且以工程目录为工作目录在编写py脚本时从工作目录开始查找自定义模块自动补齐工作目录下的相对路径。另外在打包python工程时也是从工程目录开始。因此使用IDE的默认的补全模块路径的依赖引入方式是最优选择
4.3多工程依赖的解决方案
不同于java微服务子工程之间的依赖引用python没有子工程概念只有一个完整的未拆分的工程。如果两个工程之间有模块依赖关系则需要同时部署两个工程并使用绝对路径引入另一个工程的工程目录然后从工程目录开始引入所需模块。对于常用的自定义的基础依赖也可以打包发布到公有源或私有源直接install引入模块。从工程角度考虑需要区分模块的命名空间应采用和java包名类似的方式以组织或个人的标识创建模块总包
4.4找到python工程的工程目录【方案本案】
鉴于IDE的依赖引入方式只要将python工程的工程目录加入sys.path则工程内的任何一个pycharm可成功运行的启动脚本都可以用python命令成功运行
怎样可以方便地找到一个python工程的工程目录这取决于一个工程有多少启动脚本以及每个启动脚本的位置
如果一个python工程只有一个启动脚本比如一个python文件服务器那么这个脚本应该直接放在工程一级目录下(如下图中工程目录为D:\tmp\pythonstart.py为启动脚本)这样可以顺利找到当前工程中的所有自定义依赖这是因为启动脚本路径自动拼接环境变量 如果一个python工程有多个启动脚本并且不是都在工程目录下比如一个python计算工具包那么每一个启动脚本的全局代码块都需要添加工程目录举例如下 # 当前脚本abs目录
current_script_dir os.path.split(os.path.realpath(__file__))[0]
# 当前脚本目录的上级abs目录(对于本测试用例即为python工程abs目录如果不是可继续上溯)
current_script_dir_parent os.path.split(current_script_dir)[0]
# python工程路径
python_project_dir current_script_dir_parent
if sys.path[0] ! python_project_dir:sys.path.insert(0, python_project_dir)print(添加工程目录 python_project_dir)print(print (\sys.path\))print(sys.path)