(详解)python调用另一个.py文件中的类和函数或直接运行另一个.py文件

一、同一文件夹下的调用

1.调用函数

A.py文件如下:

def add(x,y):print('和为:%d'%(x+y))

在B.py文件中调用A.py的add函数如下:

import A
A.add(1,2)

from A import add
add(1,2)

2.调用类

A.py文件如下:

class Add:def __init__(self,xx,yy):self.x=xxself.y=yydef add(self):print("x和y的和为:%d"%(self.x+self.y))

在B.py文件调用A.py文件的add函数如下:

# 第一种方法
from A import Add		# 从程序A.py中输入Add()类
a = Add(3,5)				# 对Add()类进行实例化
a.add()							# 调用类中的方法(也就是函数)
# 第二种方法
import A						# 输入程序A.py
a = A.Add(3,5)			 # 对A中的Add()类进行实例化
a.add()							# 调用类中的方法(也就是函数)

二、在不同文件夹下调用

A.py文件的文件路径为:C:\AmyPython\Test1

B.py中调用A.py文件:

import sys
sys.path.append(r'C:\AmyPython\Test1')
#python import模块时,是在sys.path里按顺序查找的。
#sys.path是一个列表,里面以字符串的形式存储了许多路径。
#使用A.py文件中的函数需要先将他的文件路径放到sys.path中
import A
a=A.A(2,3)
a.add()

还有一种方法是创建 __init__.py 文件,参考文章【更为推荐,感觉比添加路径的方式更好】
如果这文件不在一个路径下面,import就比较麻烦了,需要在被import的文件路径下面新建一个__init__.py文件,光创建就行,不需要往里面添加内容。
比如被import的文件路径是…A/b.py下面,那么只要在文件夹A下面分别新建一个__init__.py文件,然后按照下面的语句引用即可:

import A.b

进一步说明

现在文件结构是这样的

root
|
|--A文件夹
|    |--main.py
|
|--B文件夹|--b.py

现在主程序在A文件夹里,想调用B文件夹下的b.py文件,该怎么办呢?
本来以为只需要在a.py中写上:

sys.path.append('../B')
import b as bb

        但实际会报错说 No module named ‘b’
        ps. 这种直接添加相对路径的方式在Jupyter中就没有报错,不知道什么原因。
        其实这个时候用 sys.path 来查看路径的话,会发现确实添加进来了,但添加进来的是一个相对路径,所以添加路径的时候相对路径的参考地址不是当前文件,而是python根目录。

关于这个问题,解决方法有3个:

1、添加绝对路径

sys.path.append('/home/gxp/Documents/B')

2、用拼接路径的方式添加绝对路径(本质和1相同)

sys.path.append(os.path.join(os.path.dirname(__file__),'../B'))

这里join是连接两个路径,__file__是代表当前文件,dirname返回文件夹的绝对路径。所以这里添加的路径本质上是'/home/gxp/Documents/A/../B',也就是说,sys.path.append('/home/gxp/Documents/B')sys.path.append('/home/gxp/Documents/A/../B')的效果是一样的。

3、采用相对引用或其他方法

这种做法存在不少问题,有些到最后也没整明白。
这种做法和上面说的创建 __init__.py 文件的方法似乎是一样的,但这里发现没添加这个文件似乎也正常运行了。
考虑如下文档结构,主程序为 b1.py 或者 main.py。

        如果是main.py 的话会好说很多,因为它在根目录下,直接 import B.b就可以。
        但如果是b1.py的话,可以采用相对导入的方式,可参考文章 Python的绝对引用 vs 相对引用全面讲解,但是自己在用的时候会报错,就像下面这种方式是不能正常运行的,会报错说ImportError: attempted relative import with no known parent package

这似乎是非常非常普遍的问题,但也似乎没有统一的解决方案。

        好像在Pycharm中间接引用就不会出问题,所以可能是VSCode的原因?
        但不管怎么说间接引用其实不是一种很推荐的方式,就像全局变量一样,程序大了容易乱。
        尤其是如果各个子文件夹中的模块还存在互相调用的话,那写起来真的就是乱七八糟了。

import sys
from pathlib import Path
sys.path[0] = str(Path(sys.path[0]).parent.parent)  
# 将工作目录改为项目根目录,这里每一个.parent就是向上翻一级,sys.path[0]就是当前目录from B.B1 import b2 as b2
b2.b2()

这样一来,虽然主程序在一个子文件夹下,但工作目录却是根目录。所以可以像 main.py 那样通过 B.B1来解决。不过这种情况下如果各个子文件夹下的模块存在相互调用的话,也都需要在 import 时做好设置,也有些麻烦但也不是不可以。


所以整来整去,比较好的解决方案还是:
1、主程序不要放在子文件夹下,放在根目录下,然后用 import B.B1.b2的方式比较好。
2、如果主程序放在子文件夹下,一种方案是添加路径,这种方案的好处是可复用性好,但坏处是没有自动提示而且有不识别模块的警告;另一种方案就是把工作目录更改到根目录下,这种方案的好处是有自动提示写起来舒服,坏处是如果各个子文件夹内存在相互调用的话复用性会受影响。(自己还是更倾向于第二种方案,大多数人的程序其实也都有子文件夹内模块相互调用,其实问题不大)

三、运行另一个.py文件

参考文章 https://blog.csdn.net/heart_arsonists/article/details/106988694

3.1 同一目录下

import os
os.system("python filename.py")

3.2 不同目录下

如果按照上面的方法会报错

error sh: /Users//Desktop/.py: Permission denied

正确方式为

import os
os.system('{} {}'.format('python',loc))
# 或者是
os.system('python {}'.format(loc))

这里的loc为字符串,用相对路径即可。
但这样并不能把运行的文件得到的变量输出出来,如果想把结果输出出来并进一步运算,参考文章,所采用的方法是

# 所采用的方法如下
# from 变量所在文件名 import 变量名import os
# os.system('{} {}'.format('python','A/main.py'))
os.system('python {}'.format('A/main.py'))from A.main import c  # 如果在同一目录下则直接 from main import c 即可
d = c+1
print('d=',d)

参考:python调用另一个.py文件中的类和函数或直接运行另一个.py文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499859.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Newtonsoft.Json

目录 引言 1、简单使用 1.1、官方案例 1.2、JsonConvert 2、特性 2.1、默认模式[JsonObject(MemberSerialization.OptIn/OptOut)] 2.2、序列化为集合JsonArrayAttribute/JsonDictionaryAttribute 2.3、序列化该元素JsonProperty 2.4、忽略元素JsonIgnoreAttribute 2.5、…

VUE-npm ERR! C:\rj\node-v14.4.0-win-x64\nod

错误 解决办法 node -v 查看版本 npm config set registry https://registry.npmmirror.com 设置下载源 npm config get registry 获取下载源

第三个实验,三个浮点数的运算

两个浮点数相加 得到的结果再和第三个数相减 最后显示计算结果 第一步:新建项目 第二步:添加运算部件 第四步:添加浮点数值部件 第五步:修改数值部件类型 第六步:在前面板添加输出结果显示部件 第七步:连…

github-actions

文章目录 workflow触发器action市场contextsecrets 默认环境变量 workflow name: {{workflow name}} run-name: {{workflow runs name}}on: {{触发器}} #[push]env:{{定义workflow变量}}: valuejobs:{{job name}}:runs-on: {{运行机器}} #ubuntu-latestenv:{{定义job变量}}: v…

IDEA开发环境的安装与编写第一个程序

1.下载 IDEA(全称IntelliJ IDEA)是用于Java程序开发的集成环境(也可用于其他语言),它在业界被公认是最好的Java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合、代…

FPGA高速接口的发展前景如何?

从职友集有关“FPGA就业前景统计表”中可以看到2024年FPGA行业相比较2022发展前景增长80%,纵观2020——2024的形势都是逐步增长的,而且近年来芯片行业的人才薪资翻了3-5倍,2024年FPGA工程师的平均薪资在20k-30k/月,这已…

统计子矩阵

一、题目描述 P8783 [蓝桥杯 2022 省 B] 统计子矩阵 二、算法简析 2.1 二维前缀和 我们知道,只要确定了矩阵的左上顶点和右下顶点,一个矩阵就被固定了。因此,我们可以遍历这两个顶点,达到遍历所有子矩阵的目的,复杂…

spring security oauth2 之GitHub应用注册

前言: 要想使用spring security oauth2 来实现GitHub授权登录,就必须先要有一个GitHub的应用。如果使用gitee也是同理。本文介绍如果注册GitHub应用。 step1:进入到注册应用的页面 注册地址:Sign in to GitHub GitHub step2:填写信息 图中…

【HTML】HTML基础1(第一个网站!)

目录 软件使用 HTML的基本结构 案例示范 用记事本编写网页 软件使用 注释&#xff1a;<!-- -->中的内容是注释内容&#xff0c;自己写代码的时候可以没有&#xff01; HTML的基本结构 <!DOCTYPE html> <!-- 文档声明&#xff0c;位于文档最前面位置 -->…

RK3568平台开发系列讲解(基础篇)文件私有数据

🚀返回专栏总目录 文章目录 一、文件私有数据二、文件私有数据实验沉淀、分享、成长,让自己和他人都能有所收获!😄 一、文件私有数据 Linux 中并没有明确规定要使用文件私有数据,但是在 linux 驱动源码中,广泛使用了文件私有数据,这是 Linux 驱动遵循的“潜规则”,实…

column ‘_id‘ does not exist

最近把 csv 导入 SQLite 给 CursorAdapter 使用出现了这个莫名其妙的错误。 java.lang.IllegalArgumentException: column _id does not exist-CSDN博客 查找资料才明白&#xff1a;CursorAdapter 使用的数据库中必须有 _id 这个字段。 好吧&#xff0c;导入的数据库增加 _i…

搭建LNMP环境并搭建论坛和博客

目录 一、LNMP架构原理 二、编译安装Nginx 三、编译安装MySQL 四、编译安装PHP 五、配置Nginx支持PHP解析 六、安装论坛 七、安装博客 一、LNMP架构原理 LNMP架构&#xff0c;是指在Linux平台下&#xff0c;由运行Nginx的web服务器&#xff0c;运行PHP的动态页面解析程序…