os和sys模块

os模块

一、什么是os模块

os模块提供了多数操作系统的功能接口函数。
当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件、目录打交道,所以离不了os模块。

导入os模块

import os

二、常用的os模块命令

os.name

os.name——name顾名思义就是’名字’,这里的名字是指操作系统的名字,主要作用是判断目前正在使用的平台,并给出操作系统的名字,如Windows 返回 ‘nt’; Linux 返回’posix’

注意该命令不带括号,它是一个属性,除了第一个命令不带括号之外,以下命令基本都带括号。

print(os.name)
# nt
os.getcwd()

os.getcwd()——全称应该是’get current work directory’,获取当前工作的目录,如:返回结果为:‘C:\Program Files\Python36’。

等于linux中命令的pwd

print(os.getcwd())
# c:\Users\123\Desktop
os.listdir(dir)

os.listdir(path)——列出path目录下所有的文件和目录名,返回一个给定path下所有文件的一个列表。相当于linux中的ls

path参数可以省略,如果省略,则默认返回当前目录下所有文件

path参数可以是相对路径,也可以是绝对路径

print(os.listdir())
# path参数没填默认返回当前目录,当前目录是桌面,则会返回桌面上所有的文件及文件夹
print(os.listdir('./numpy练习/'))
# ['111.py', '创建numpy数组.py', '统计函数.py', '连接两个数组.py']

所有的内容以列表的形式全部列举出来,其中没有区分目录和文件。

有关path需要注意的坑

在path使用绝对路径时,有一个需要特别注意的坑,而这个坑其实跟windows和linux它们的命令的区别有关

DOS,cmd以及Linux的区别

其实拿着三个作为比较是为了接触一些混淆,以便搞清楚下面path中在linux和windows上的区别。

DOS是英文Disk Operating System的缩写,意思是“磁盘操作系统”。其实DOS是一种操作系统,和Windows以及linux是一种概念。

windows中的cmd是command的缩写,意思是命令提示符。在windows操作系统里进的DOS(即输入 CMD 进命令提示符)不是纯DOS,只是为方便某些需求而建立的,而纯DOS本身就是一种操作系统。(两者的区别:比如你可以在纯DOS下删除你的windows系统,但在cmd里却不能,因为你不可能"在房子里面拆房子吧?")

虽然DOS和cmd不是同一种概念,但是cmd中也包含了DOS中的大部分命令,而我们现在越不会去单独谈论DOS这种操作系统了。所以我们一般把DOS和cmd都统称为windows的命令行。

随着发展,DOS系统已经被淘汰了,所以cmd在生成环境下也用的很少(只是在我们自己电脑上偶尔用用的),现在在工作中基本上都是要在服务器上用Linux命令的。

Linux基本本身就是用命令行来运行的,不需要通过cmd来启动,所以Linux中是没有cmd的,它的命令都是通过Terminal(终端)的。Linux如果没有安装桌面的话,直接就登陆的是终端。

总结来说:

一种是window下的命令行:叫做DOS和cmd,而还有一种是Linux中的命令行:Terminal。

文件路径中的/\ 的区别

上一节说清楚了windowslinux的命令行的区别,我们下面也不提cmd和DOS了,直接用windowslinux作为区分。

windowslinux下的路径层次符号是不同的

Linux使用斜杆 / 作为路径分隔符,Linux命令下的路径分隔符只能使用斜杠 /,而无法识别反斜杠 \

image-20211218173447810

上图中我们可以看到Linux命令中输入反斜杠 \,系统无法识别其为一个路径分隔符,报错的信息为找不到Desktoppython文件,其把这整个都当作一个文件名了。

web应用最新使用在Linux系统上面,所以目前所有的网络地址都采用 斜杆/ 作为分隔符

image-20211218174210042

而Windows由于已经使用 斜杆/ 作为DOS命令提示符的参数标志了

image-20211218095117897

在Linux环境中,用双减号(“–”)和减号(“-”)表示命令行参数。

减号(“-”)一般是对应着双减号(“–”)全命令的缩写

如下面ls -a就是ls --a的缩写

image-20211218095410798

为了不混淆,所以windows上采用 反斜杠\ 作为路径分隔符。所以目前windows系统上的文件浏览器都是用 反斜杠\ 作为路径分隔符。随着发展,**DOS系统已经被淘汰了,命令提示符也用的很少,现在我们自己输入命令时:斜杆 / 和反斜杠 \ 都可以作为路径分隔符使用(可以完全混着用),所以没有影响。只是在windows下本身显示的是反斜杠 \ **

image-20211218172910003

小彩蛋:

虽然在windows的命令中也能识别斜杆 / 作为分隔符,但是你使用斜杆 / 的时候按Tab并不会进行路径的智能补全。毕竟它原生是用反斜杠\ 作为路径分隔符,所以在cmd中只能用反斜杠\ 再按Tab才能有Linux下按Tab那种自动补全的丝滑感。

windows文件浏览器上显示的路径分隔符是和命令行中一致的:反斜杠\

image-20211218174030534

总结来说:

  • 在windows上显示的地址都是采用 反斜杠\ 作为路径分隔符,但在我们输入的命令中斜杆 / 和反斜杠 \ 都可以作为路径分隔符使用。
  • 在Linux上上显示的地址都是采用 斜杠/ 作为路径分隔符,在我们输入的命令中也只支持斜杆 / 作为路径分隔符使用。

拓展结论:
(1)浏览器地址栏网址使用 斜杆/ ;
(2)windows文件浏览器上使用 反斜杠\ ;

在代码中的地址,以及\\的用法

记住双\\只会出现在windows代码中的路径分隔符,在其他所有命令行中都不会被识别。

windows系统的地址栏能够识别单反斜杠\,而不能识别双反斜杠\\这是系统文件系统自身的约定,路径层次使用\区分而不是使\\来区分
所以F:\Office\Trunk\__Out\Pro Debug\Bin\\OfficeInfo.dll这样是不正确的。

而在程序中,字符串中单斜杠\的意思是转义。如\n\t等。

所以代码中的字符串中\\转义后被理解为\,而\才能够被windows操作系统的文件系统所理解,比如用字符串表示上述路径:“F:\\Office\\Trunk\\__Out\\Pro Debug\\Bin\\OfficeInfo.dll”。除以转义的单斜杠\后就是标准的windows路径F:\Office\Trunk\__Out\Pro Debug\Bin\OfficeInfo.dll

import os
print(os.listdir('C:\Users\123\Desktop\numpy练习'))
# 报错
#  File "c:\Users\123\Desktop\numpy练习\111.py", line 2
#     print(os.listdir('C:\Users\123\Desktop\numpy练习'))
#                      ^
# SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

print(os.listdir('C:\\Users\\123\\Desktop\\numpy练习'))
# 正常输出结果
# ['111.py', '创建numpy数组.py', '统计函数.py', '连接两个数组.py']

image-20211218175834787

其实我们在vscode中的高亮也可以看出来,成功转义时,整个被转移片段都会被高亮,如上图所示。

同理,如果想要表示\\,可以写作\\\\(对,你没看错,每一个反斜杠\都需要一个 反斜杠\来转移,所以双反斜杠最后在代码中是需要4个反斜杠的)。

相比于每个地址都去使用双反斜杠作为转义,还有一种更简便的用法,就是在字符串前加r'....'表示raw原始字符串(即字符串的反斜杠\不再作为转义的意思)

import os
print(os.listdir(r'C:\Users\123\Desktop\numpy练习'))
# 使用r'....'的形式表示原始字符串
# ['111.py', '创建numpy数组.py', '统计函数.py', '连接两个数组.py']

看到这个r想到了什么?

我们的f'...'字符串表示格式化字符串

a = 1
f'a = {a}' 
#代表了字符串 'a = 1'

而用字符串表示linux中的路径就更简单了,因为linux中是斜杠/作为路径分隔符的 。

单斜杠在字符串中没有转义的坑,所以直接用/user/dd.txt即可。

而我们上一节说到windows命令的路径中也可以使用斜杠/,所以我们也可以直接使用

import os
print(os.listdir('C:/Users/123/Desktop/numpy练习'))
# windows命令的路径中也可以使用斜杠`/`
# ['111.py', '创建numpy数组.py', '统计函数.py', '连接两个数组.py']

# 我们甚至可以来个骚操作
print(os.listdir('C:/Users\\123/Desktop\\numpy练习'))
# 只要搞清楚斜杠`/`和转义反斜杠`\`的用法,windows中的path地址可以混着用
#  ['111.py', '创建numpy数组.py', '统计函数.py', '连接两个数组.py']

对应在cmd中就是这种骚操作

image-20211218181944047

但是没必要自己去用这种骚操作,理解windows中斜杠/和反斜杠\都适用就可以了

总结

windows下表示路径的三种方式:

image-20211218180930564

Linux下直接使用斜杠/作为分隔符即可

Trick

说了上面那么多

总结下来由于在字符串中反斜杠\有转义的坑,所以我们在任何程序中的路径都统一用斜杠/作为分隔符即可。

因为本身windows路径也支持斜杠/,所以我们没必要去搞的那么复杂,记住这个规则就可以了。上面的路径字符串中的双反斜杠\\和原始字符串r'...'都只是为了你在看其他人的代码的时候不会感到迷惑。而自己用的时候不管在windows下还是linux下都去用斜杠/表示路径分隔符就可以了。

合并/拆分路径

os库中支持对路径的拆分和合并

os中认为每一个路径都由文件路径(dirname)和文件名(basename)所组成:

它们由最后一个’/’分隔,最后一个’/’之后的即为文件名(注意它可以是一个dir也可以是一个file)
以此衍生的功能就是对文件路径和文件名的拆分(path.split)和合并(path.join)

以下例子中我们都以名为’python文件’的目录下的test目录为例

pathname = './python文件/test'
os.path.dirname(path)

os.path.dirname(path)——返回文件路径

# pathname = './python文件/test'
print(os.path.dirname(pathname))
# './python文件'

返回该文件所在的母目录,即’/’之前的文件路径

os.path.basename(path)

os.path.basename(path)——返回文件名

# pathname = './python文件/test'
print(os.path.basename(pathname))
# 'test'

返回该文件的名字

os.path.split(path)

os.path.split(path)——返回路径的(目录,文件名)的tuple,即将目录和文件名分开,而不是一个整体。

此处只是把前后两部分分开成(dirname, basename)而已。就是找最后一个’/’。

# pathname = './python文件/test'
print(os.path.split(pathname))
# ('./python文件', 'test')
os.path.join(path, name)

os.path.join(path, name)——连接目录和文件名,与os.path.split(path)相对。其作用是在某个文件所在的文件夹中创建其他文件时可利用先拆分得到母目录(dirname),然后再合并一个新文件名得到新path。

# pathname = './python文件/test'
# 拆分得到母目录
parent, _ = os.path.split(pathname)
print(parent)
# './python文件'

# 合并目录和新文件名
new_filename = 'new_test'
print(os.path.join(parent,new_filename))
# './python文件\new_test'

# # 创建新文件
# os.mkdir(os.path.join(parent,new_filename))

思考为什么要这么麻烦先拆再合

拿到母目录parent不可以直接使用parent = os.getcwd()吗

注意这样的想法是不对的,os.getcwd()的目录是你当前py文件所在的路径,比如说我上面的py文件是在桌面上创建的,所以拿到的是c:\Users\123\Desktop。而我是想在pathname这个文件所在的’./python文件’的母目录中创建。所以必须要先拆分后合并

当然下面介绍的chdir可以改变当前路径后再用os.getcwd()也是可以的,不过就麻烦一些了

创建/删除文件夹dir

注意下面的命令都是对目录层面操作

输入参数的dir都为一个文件夹地址,如果输入一个文件地址则会报错

os.mkdir(dir)

os.mkdir(path)——创建path指定的目录,该参数不能省略。

等于linux命令中的mkdir

注意mkdir只能创建目录,想创建文件时加上特定后缀也是不可以的,

例如,如果想创建一个’test.txt’的文本文件,os.mkdir(‘test.txt’)后只能创建名为’test.txt’的为文件夹

# 在名为'python文件'的文件夹下创建一个名为'testdir'文件夹
path = './python文件/'
new_dir_name = 'testdir'
newdir = os.path.join(path,new_dir_name) 
# 这里用到了os.path.join()的方法,下面会用到
os.mkdir(newdir)
os.makedirs(recur_dirs)

注意:os.mkdir(path)只能建立一层目录,要想递归创建多层目录可用:os.makedirs()

# 在名为'python文件'的文件夹下创建两层文件夹'/test2/test2.1'
muti_dir = './python文件/test2/test2.1'
os.makedirs(muti_dir)
# 注意,如果此时用os.mkdir(muti_dir)时会报错!
os.rmdir(empty_dir)

os.rmdir(path)——删除path指定的单个空文件夹,该参数不能省略。

如果删除非空文件夹会报错 “目录不是空的。”

注意:只要文件夹里有任何内容就是非空文件夹

一个文件夹不管是包含了空文件夹还是空文件,只要包含了任何内容就是非空文件夹

# 删除刚刚创建的空文件夹
newdir = './python文件/testdir'
os.rmdir(newdir)
shutil.rmtree(recur_dirs)

os库中并不支持删除非空文件夹,如果想像linux中 rm -r dir的命令一样删除文件夹中所有的内容的话,要利用shutil库。shutil.rmtree的命令像删除树一样递归的删除该dir以及该dir下所有的内容。

# none_empty_dirs中包含了test1和test2文件夹,test2文件夹下还有'666.txt'文件
import shutil
shutil.rmtree(none_empty_dirs)
# 执行后整个none_empty_dirs消失

创建/删除文件file

注意下面的命令都是对文件层面操作

输入参数的file都为一个文件夹地址,如果输入一个文件夹地址则会报错

open(file,‘w’)

wins创建空文件只有这种方式,os库中的创建文件函数不能用在wins下

newfile = './python文件/666.txt'
open(newfile, 'w')

os.mknod(file)

该函数只能用在linux中,windows没有node的概念,所以不支持

os.mknod(path) ——创建path指定的空文件,该参数不能省略。

os.remove(file)

os.remove(path)——删除path指定的文件,该参数不能省略。

等于linux中的rm filename 的指令

filepath = './python文件/666.txt'
os.remove(filepath)

其他常用指令

os.path.isfile(path)

os.path.isfile(path)——判断指定对象是否为文件。是返回True,否则False

os.path.isdir(path)

os.path.isdir(path)——判断指定对象是否为目录。是True,否则False。

os.path.exists(path)

os.path.exists(path)——检验指定的对象是否存在。是True,否则False.例

os.chdir(path)

os.chdir(path)——'change dir’改变目录到指定目录

等于linux中的cd命令

print(os.getcwd())
# c:\Users\123\Desktop

os.chdir('./python文件/')
print(os.getcwd())
# c:\Users\123\Desktop\python文件
os.path.getsize()

os.path.getsize()——获得文件的大小,如果为目录,返回0

os.path.abspath(path)

os.path.abspath(path)——输入一个文件路径,获得其绝对路径。

# 当前的工作路径是桌面
path = './python文件/'
print(os.path.abspath(path))
# c:\Users\123\Desktop\python文件

sys库

一、sys库介绍以及常见函数列表

sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:python解释器。
image-20211102140013743

# 导入sys模块
import sys

当Python执行import sys语句的时候,它在sys.path变量中所列目录中寻找sys.py模块。如果找到了这个文件,这个模块的主块中的语句将被运行,然后这个模块将能够被你 使用 。注意,初始化过程仅在我们 第一次 输入模块的时候进行。另外,“sys”是“system”的缩写。

Sys模块函数之多,我只能选取自己认为比较实用的一些函数列在此处。借马云找员工的说法,”找最合适的而不是最天才的”,这句话,我个人觉得在很多方面都能适应,学习也不在话下。Sys模块功能的确很多,但我们应该将重点放在那些功能才是最适合我们的,为此,我列的这些函数,就是我认为比较适合我以后开发的函数。

二、sys常用函数介绍

sys.argv

很多人会想,如何给我的程序在外部传递参数到我的程序中呢呢?这个就可以用sys.argv实现。如:test.py

# test.py中的内容
import sys
args = sys.argv
print(args)

注意:sys.argv命令是个sys模块中的属性,调用时不需要括号

sys.argv其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该将程序保存了,从外部来运行程序并给出参数。

# 在cmd中输入
(base) C:\Users\123\Desktop>python test.py 1 2 3

>>> ['test.py', '1', '2', '3']

看到对应的关系了吗?

sys.argv变量是一个字符串的列表,这意味着即使命令行敲入的是数字也是字符串类型。特别地,sys.argv包含了命令行参数的列表,即使用命令行传递给你的程序的参数,传入参数时,各参数用空格分隔

注意,脚本的名称总是sys.argv列表的第一个参数即sys.argv[0]

所以,在这各例子中,'test.py’是sys.argv[0]、'1’是sys.argv[1]、'2’是sys.argv[2]以及’3’是sys.argv[3]

所以一般为了拿到所有参数我们一般提取sys.argv[1:]

import sys
args = sys.argv[1:]
# 此时args就完全是用户输入的参数列表

sys.platform

显示当前的操作系统类别。这就相当于os中的os.name
os.name一样,是一个属性,调用时不需要括号。

假设,我们想实现一个清除终端,linux下用clear, windows下用cls

os_type = sys.platform
print(os_type)
# 因为我是win操作系统下,win32

if os_type==”linux” or os_type==”linux2”:
    cmd=”clear”
else:
    cmd=”cls”

sys.path

sys.path是所有库所在的环境列表,包含了python在调用的所有的库(module)所在的环境。

这个环境有什么用呢?

在执行import module_name的时候

python会在sys.path所在的所有目录中进行搜索这个module_name,找到后进行调用

# 当前目录是桌面
sys.path
#['c:\\Users\\123\\Desktop', 'D:\\Anaconda3\\python38.zip', 'D:\\Anaconda3\\DLLs', 'D:\\Anaconda3\\lib', 'D:\\Anaconda3', 'C:\\Users\\123\\AppData\\Roaming\\Python\\Python38\\site-packages', 'D:\\Anaconda3\\lib\\site-packages', 'D:\\Anaconda3\\lib\\site-packages\\locket-0.2.1-py3.8.egg', 'D:\\Anaconda3\\lib\\site-packages\\win32', 'D:\\Anaconda3\\lib\\site-packages\\win32\\lib', 'D:\\Anaconda3\\lib\\site-packages\\Pythonwin']

大家以后写好的模块就可以放到上面的某一个目录下,便可以正确搜索到了。当然大家也可以添加自己的模块路径。sys.path.append(“my special module path”).

sys.path包含输入模块的目录名列表。sys.path的第一个字符串一定是当前py文件所在的目录,这表明当前目录也是sys.path的一部分,所以你可以直接将调用当前py文件所在目录下的所有模块,其他的与PYTHONPATH环境变量是相同的。否则,你得把你的模块放在sys.path所列的目录之一

sys.modules

如果说sys.path包含了库的所有的环境,sys.modules则是看现在py文件中调用的所有的库的详细信息。sys.path是一个字典,它的key是库的名字,而value则是库所要用的文件的路径

import sys
import numpy
print(sys.modules)

# {'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>,.....'numpy._globals': <module 'numpy._globals' from 'D:\\Anaconda3\\lib\\site-packages\\numpy\\_globals.py'>, 'numpy.__config__': <module 'numpy.__config__' from 'D:\\Anaconda3\\lib\\site-packages\\numpy\\__config__.py'>, 'numpy.version': <module 'numpy.version' from 'D:\\Anaconda3\\lib\\site-packages\\numpy\\version.py'>,....}

可以看出上面在调用sysnumpy后,sys.modules显示了关于他们的详细信息,‘sys’ 和 ‘builtins’ 都是来自python自带的库。而后面一堆关于numpy文件的调用则是来自于anacondas3中的扩展包中的。

sys.stdin,sys.stdout,sys.stderr

stdin , stdout , 以及stderr 变量包含与标准I/O 流对应的流对象。它们可以更好地控制输入和输出的位置。

sys.stdin

sys.stdin是标准化输入的方法,它接受从键盘中输入的字符串,

最常用的函数和读取文件的函数很像,sys.stdin.readline()sys.stdin.readlines()(等同于f.readline(), f.readlines()

sys.stdin.readline()用的比较少,其效果和input()函数完全一致

import sys
print('Please input your name: ')
name = sys.stdin.readline()
print('Hello ', name)

# cmd中
Plase input your name:
Zhang
Hello  Zhang

# 等价于
name = input('Please input your name: ')
print('Hello ', name)
# cmd中
Plase input your name: Zhang
Hello  Zhang

使用sys.stdin.readline()可以实现从键盘的标准输入,其中默认输入的格式是字符串,如果是int,float类型则需要强制转换。

sys.stdin.readline()input()有两个不同点

我们先来看例子中发现不同点

name1 = input('Please input your name (input()): ')
print('Hello ', name1)

print('Please input your name (sys.stdin.readline()): ')
name2 = sys.stdin.readline()
print('Hello ', name2)

print('结果细节比较')
li = [name1, name2]
print(li)
image-20211104101517842
  1. 输入时不同

    input()输入时紧接着输入,sys.stdin.readline()输入是另起一行,但是这点区别其实不大,只要name = input(‘Please input your name: \n’)就可以完全达到上面的效果

  2. 输出不同

    input()输出后面就是’‘用户输入的内容’’,sys.stdin.readline()输出是’‘用户输入的内容\n’’,也就是会自带个换行符

但本质上来说sys.stdin.readline()用法和input()的效果一致,没什么特殊用处,所以其完全可以被input()所替代

相比来说,sys.stdin.readlines()更强大,它可以做到输入多行

除非用户输入ctrl+z后再按回车确定打断

import sys
print('终端输入')
print('please input name1')
name1 = sys.stdin.readline()
print('please input name2')
name2 = sys.stdin.readline()
print('please input other names, ctrl+z+enter to stop')
names = sys.stdin.readlines() # readlines()可以一次输入多行

print('输出')
print(name1)
print(name2)
print(f'names: {names}')

我们先来看结果

image-20211104102633527

我们可以看到输出时sys.stdin.readline()就和input()的作用一样

但是注意sys.stdin.readline()的输出之间是空了一行的这是因为本身sys.stdin.readline()的输出会自带一个换行符’\n’,再加上print(‘…’)最后也会自动在结果中加上一个换行符’\n’,所以总体来说会在中间空一行。

sys.stdin.readlines()会一次读取多行输入,除非用户输入ctrl+z后打断表示用户已经停止了输入,否则所有的回车都会默认是换行,就算一行不输入直接按回车不会终止输入
最后的输出是用户在输入过程中所有内容的内容列表,其中列表中每一个元素对应了用户输入的每一行的内容

本质上sys.stdin.readline()就对应了读取文件的f.readline()的,都是每次读取一行(并且会包含每一行的换行符)。

sys.stdin.readlines()就对应了读取文件的f.readlines()的,都是每次读取文件之后的所有内容并形成内容列表(并且列表中每一个元素都会包含每一行的换行符)。

它们唯一不同的是,f.readline()f.readlines()的读取对象是文件,sys.stdin.readline()sys.stdin.readlines()的读取对象是终端输入罢了。

sys.stdin.readlines()在有些网站的笔试中非常重要(如牛客等),如果要获取行数未知的输入,input()几次就成了问题(因为input()一次就是一行罢了),而直接用sys.stdin.readlines()可以获取一次的所有多行输入(并不需要知道有多少行),后续得到内容列表后,使用len()和索引就能正常的操作了。
不过注意内容列表每一个元素最后都带有’\n’换行符,除去的话要配合使用strip()。

input_ = [line.strip() for line in sys.stdin.readlines()]
sys.stdout

sys.stdout是将所有print中的结果重新定向输出到指定文件

import sys
print(1)
sys.stdout = open('log', 'a')
print('the error message is written to errlog')
print(2)
print(3)

执行sys.stdout = open('log', 'a')后,之后print打印信息不会在屏幕上显示,而是会写到log文件中

结果:

image-20211102155112387 image-20211102155101649

可以看出执行sys.stdout = open('log', 'a')之前第2行的print(1)输出到了终端

执行sys.stdout = open('log', 'a')之后所有的内容都写入了log文件

区别于不使用sys.stdout,直接调用file参数将指定内容写入日志

temp = open('log', 'a') # 指定输出的文件位置
print(1)
print('cool,you write your first log', file=temp) 
# 指定print中的file参数输入到log文件中
print(2)
print(3)

结果

image-20211102155410957

说明只有指定file参数的print写入了log中

image-20211102155453975

而其他的1,2,3都输入到了终端

这种的应用场景是只用记录特定print的到log日志中
区别于sys.stdout,它会将执行后所有的print都写入log日志中

补充知识点:

注意一般open后面的参数我们只跟’w’和’r’,那这里为什么是’a’呢

实际上**'a’表示追加**

a 以追加模式打开 (从 EOF 开始, 必要时创建新文件,即当没有文件时创建新文件)

因为log日志一般都会记录所有的运行结果,不会因为第二次运行就覆盖了第一次运行的结果

sys.stderr

sys.stderr是将标准错误信息重定向输出到错误文件中

运行代码后错误信息不会在屏幕上显示,会写入到errlog文件中

import sys
sys.stderr = open('errlog', 'a')
wrong

上面的wrong是我未定义的参数,这是我故意写的错误

执行后结果

image-20211102160009959

发现执行sys.stderr = open('errlog', 'a')后续程序所有的报错信息都将写入errlog文件中,由此就可以记录报错日志

扩展用法

import sys
sys.stderr = open('errlog', 'a')
temp = sys.stderr
print('the error message is written to errlog', file=temp)
print(1)
wrong

第4行的print的信息和第6行的报错信息都写入了errlog文件中

image-20211102160132474

第5行的print信息打印到了终端

image-20211102160253434

从上述例子可以看出sys.stdoutsys.stderr还是有本质区别的

sys.stdout专门负责print中的输出:

只要执行sys.stdout = open('log', 'a')之后所有的print内容都写入了log文件

sys.stderr专门负责err中的输出:

只要执行sys.stderr = open('errlog', 'a')之后所有的报错内容都写入了errlog文件,而不会影响print的信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值