5-Python-文件操作、异常、模块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fly910905/article/details/72676412

知识点

文件操作

<1>打开文件

python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件

示例如下:

open(文件名,访问模式)

f = open('test.txt', 'w')

说明:

访问模式 说明
r 只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式
w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+ 打开一个文件用于读写文件指针将会放在文件的开头
w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

<2>关闭文件

close( )

示例如下:

# 新建一个文件,文件名为:test.txt

f = open('test.txt', 'w')

# 关闭这个文件

f.close(

文件的读写

<1>写数据(write)

使用write()可以完成向文件写入数据

  • demo:
f = open('test.txt', 'w')

f.write('hello world, i am here!')

f.close()

<2>读数据(read)

使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度单位是字节),如果没有传入num,那么就表示读取文件中所有的数据

  • demo:
f = open('test.txt', 'r')

content = f.read(5)

print(content)

print("-"*30)

content = f.read()

print(content)

f.close()

<3>读数据(readlines

就像read没有参数时一样,readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素

#coding=utf-8

f = open('test.txt', 'r')

content = f.readlines()

print(type(content))

i=1

for temp in content:

print("%d:%s"%(i, temp))

i+=1

f.close()
  • 运行现象:

<4>读数据(readline

#coding=utf-8

f = open('test.txt', 'r')

content = f.readline()

print("1:%s"%content)

content = f.readline()

print("2:%s"%content)

f.close()

 

 

应用1:制作文件的备份 

  1. 任务描述
  2. 输入文件的名字,然后程序自动完成对文件进行备份
#coding=utf-8
oldFileName = raw_input("请输入要拷贝的文件名字:")
oldFile = open(oldFileName,'rb')
# 如果打开文件
if oldFile:
    # 提取文件的后缀
    fileFlagNum = oldFileName.rfind('.')
    if fileFlagNum > 0:
        fileFlag = oldFileName[fileFlagNum:]
    # 组织新的文件名字
    newFileName = oldFileName[:fileFlagNum] + '[复件]' + fileFlag
    # 创建新文件
    newFile = open(newFileName, 'wb')
    # 把旧文件中的数据,一行一行的进行复制到新文件中
    for lineContent in oldFile.readlines():
        newFile.write(lineContent)
    # 关闭文件
    oldFile.close()
    newFile.close()

文件的定位读写

<1>获取当前读写的位置

在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取

# 打开一个已经存在的文件

f = open("test.txt", "r")

str = f.read(3)

print "读取的数据是 : ", str



# 查找当前位置

position = f.tell()

print "当前文件位置 : ", position



str = f.read(3)

print "读取的数据是 : ", str



# 查找当前位置

position = f.tell()

print "当前文件位置 : ", position



f.close()

<2>定位到某个位置

如果在读写文件的过程中,需要从另外一个位置进行操作的话,可以使用seek()

seek(offset, from)有2个参数

offset:偏移量

from:方向

0:表示文件开头

1:表示当前位置

2:表示文件末尾

demo:把位置设置为:从文件开头,偏移5个字节

# 打开一个已经存在的文件

f = open("test.txt", "r")

str = f.read(30)

print "读取的数据是 : ", str



# 查找当前位置

position = f.tell()

print "当前文件位置 : ", position



# 重新设置位置

f.seek(5,0)



# 查找当前位置

position = f.tell()

print "当前文件位置 : ", position



f.close()

demo:把位置设置为:离文件末尾,3字节处

# 打开一个已经存在的文件

f = open("test.txt", "r")



# 查找当前位置

position = f.tell()

print "当前文件位置 : ", position



# 重新设置位置

f.seek(-3,2)



# 读取到的数据为:文件最后3个字节数据

str = f.read()

print "读取的数据是 : ", str



f.close()

文件重命名、删除

有些时候,需要对文件进行重命名、删除等一些操作,python的os模块中都有这么功能

<1>文件重命名

os模块中的rename()可以完成对文件的重命名操作

rename(需要修改的文件名, 新的文件名)

import os

os.rename("毕业论文.txt", "毕业论文-最终版.txt")

 

<2>删除文件

os模块中的remove()可以完成对文件的删除操作

remove(待删除的文件名)

import os

os.remove("毕业论文.txt")

 

文件夹的相关操作

实际开发中,有时需要用程序的方式对文件夹进行一定的操作,比如创建、删除等

就像对文件操作需要os模块一样,如果要操作文件夹,同样需要os模块

<1>创建文件夹

import os

os.mkdir("张三")

<2>获取当前目录

import os

os.getcwd()

<3>改变默认目录

import os

os.chdir("../")

<4>获取目录列表

import os

os.listdir("./")

<5>删除文件夹

import os

os.rmdir("张三")

应用2:批量修改文件名

 #coding=utf-8
    # 批量在文件名前加前缀
    import os
    funFlag = 1 # 1表示添加标志  2表示删除标志
    folderName = './renameDir/'
    # 获取指定路径的所有文件名字
    dirList = os.listdir(folderName)
    # 遍历输出所有文件名字
    for name in dirList:
        print name
        if funFlag == 1:
            newName = '[东哥出品]-' + name
        elif funFlag == 2:
            num = len('[东哥出品]-')
            newName = name[num:]
        print newName
        os.rename(folderName+name, folderName+newName)

异常介绍

示例(打开一个不存在的文件123.txt):

print '-----test--1---'
open('123.txt','r')
print '-----test--2---'

运行结果:打开一个不存在的文件123.txt,当找不到123.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory:123.txt (没有123.txt这样的文件或目录)

当Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"

捕获异常

<1>捕获异常 try...except...

    try:
        print '-----test--1---'
        open('123.txt','r')
        print '-----test--2---'
    except IOError:
        pass
  1. 此程序看不到任何错误,因为用except 接收了产生IOError错误,并添加了处理错误的方法
  2. pass 表示实现了相应的实现,但什么也不做;如果把pass改为print语句,那么就会输出其他信息

<2>获取异常的信息描述

    try:
        print num
    except IOError:
        print '产生错误了;'

上例程序,已经使用except来捕获异常了,为什么还会看到错误的信息提示?

except捕获的错误类型是IOError,而此时程序产生的异常为 NameError ,所以except没有生效

修改后的代码为:

    try:
        print num
    except NameError:
        print '产生错误了;'

<3> except捕获多个异常

#coding=utf-8
try:
    print '-----test--1---'
    # 如果123.txt文件不存在,那么会产生 IOError 异常
    open('123.txt','r')
    print '-----test--2---'
    # 如果num变量没有定义,那么会产生 NameError 异常
    print num
except (IOError,NameError), errorMsg: 
    #如果想通过一次except捕获到多个异常可以用一个元组的方式
    # errorMsg里会保存捕获到的错误信息
    print errorMsg
  1. 如果想捕获所有的异常,可以省略 except后面的变量
  2. 但是这种方法不建议大家使用,会隐藏一些开发者没有想到的异常情况

<4> try...finally...

try...finally...语句用来表达这样的情况

不管线捕捉到的是什么错误,无论错误是不是发生,这些代码“必须”运行,比如文件关闭,释放锁,把数据库连接返还给连接池等

    import time
    try:
        f = file('poem.txt')
        while True: # our usual file-reading idiom
            line = f.readline()
            if len(line) == 0:
                break
            time.sleep(2)
            print line,
    finally:
        f.close()
        print 'Cleaning up...closed the file'
  1. 程序读poem.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl-c中断/取消程序。
  2. 我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。

<5> else

咱们应该对else并不陌生,在if中,它的作用是当条件不满足时执行的实行;同样在try...except...中也是如果,即如果没有捕获到异常,那么就执行else中的事情

    try:
        num = 100
        print num
    except NameError, errorMsg:
        print('产生错误了:%s'%errorMsg)
    else:
        print('没有捕获到异常,真高兴')
    finally:
        print('我一定会执行的哦')

抛出异常

你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是ErrorException类的子类

下面是一个引发异常的例子:

    class ShortInputException(Exception):
        '''你定义的异常类。'''
        def __init__(self, length, atleast):
            Exception.__init__(self)
            self.length = length
            self.atleast = atleast
    try:
        s = raw_input('请输入 --> ')
        if len(s) < 3:
            # raise引发一个你定义的异常
            raise ShortInputException(len(s), 3)
    except EOFError:
        print '/n你输入了一个结束标记EOF'
    except ShortInputException, x:#x这个变量被绑定到了错误的实例
        print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (x.length, x.atleast))
    else:
        print '没有异常发生.'

运行结果如下:

    $ python raising.py
    请输入 -->
    你输入了一个结束标记EOF
    $ python raising.py
    请输入 --> --> ab
    ShortInputException: 输入的长度是 2, 长度至少应是 3
    $ python raising.py
    请输入 --> abc
    没有异常发生.

模块介绍

<1>Python中的模块

有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include"引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?

Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。

说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块

<2>import

Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。

 import module1,mudule2...
  • 当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
  • 在调用math模块中的函数时,必须这样引用:

模块名.函数名

有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以以下方法实现

from 模块名 import 函数名1,函数名2...

  • 不仅可以引入函数,还可以引入一些变量

注意:

通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function( ),在模块B中也有函数function( ),如果引入A中的function在先、B中的function在后,那么当调用function函数的时候,是去执行模块B中的function函数。

如果想一次性引入math中所有的东西,还可以通过from math import *来实现,但是不建议这么做

<3>fromimport

Pythonfrom语句让你从模块中导入一个指定的部分到当前命名空间中。

语法如下:

from modname import name1[, name2[, ... nameN]]

例如,要导入模块fibfibonacci函数,使用如下语句:

from fib import fibonacci

这个声明不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入

<4>from … import *

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:

from modname import *

这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

<5>定位模块

  • 当你导入一个模块,Python解析器对模块位置的搜索顺序是:

当前目录

如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。

如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/

模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

模块制作

<1>定义自己的模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。

比如有这样一个文件test.py,在test.py中定义了函数add

test.py

    def add(a,b):
        return a+b

<2>调用自己定义的模块

那么在其他文件中就可以先import test,然后通过test.add(a,b)来调用了,当然也可以通过from test import add来引入

main.py

   import test
    result = test.add(11,22)
    print(result)

<3>测试模块

在实际开中,有时一个模块,是一个开发人员进行编写,为了让整个模块中的功能都达到想要的效果,有时编程人员会自行在py文件中添加一些测试信息,例如:

test.py

    def add(a,b):
        return a+b
    # 用来进行测试
    ret = add(12,22)
    print('int test.py file,,,,12+22=%d'%ret)

如果此时,在其他py文件中引入了此文件的话,想想看,测试的那段代码是否也会执行呢!

main.py

    import test
    result = test.add(11,22)
    print(result)

运行现象:

至此,可发现test.py中的测试代码,应该是单独执行test.py文件时,才应该执行的,不应该是其他的文件中引用而执行

为了解决这个问题,python在执行一个文件时有个变量__name__

 

总结:

可以根据__name__变量的结果能够判断出,是直接执行的python脚本还是被引入执行的,

从而能够有选择性的执行测试代码

Python中的包

1.python中的包

包将有联系的模块组织在一起,有效避免模块名称冲突问题,让应用组织结构更加清晰

假定我们的包的例子有如下的目录结构:

Phone/
    __init__.py
    common_util.py
    Voicedta/
        __init__.py
        Pots.py
        Isdn.py
    Fax/
        __init__.py
        G3.py
    Mobile/
        __init__.py
        Analog.py
        igital.py
    Pager/
        __init__.py
        Numeric.py

Phone 是最顶层的包,Voicedta 等是它的子包。 我们可以这样导入子包:

import Phone.Mobile.Analog

Phone.Mobile.Analog.dial()

你也可使用 from-import 实现不同需求的导入

第一种方法是只导入顶层的子包,然后使用属性/点操作符向下引用子包树

from Phone import Mobile

Mobile.Analog.dial('555-1212')

此外,我们可以还引用更多的子包:

from Phone.Mobile import Analog

Analog.dial('555-1212')

事实上,你可以一直沿子包的树状结构导入:

from Phone.Mobile.Analog import dial

dial('555-1212')

在我们上边的目录结构中,我们可以发现很多的 __init__.py 文件。这些是初始化模块from-import 语句导入子包时需要用到它。 如果没有用到,他们可以是空文件。

包同样支持 from-import all 语句

from package.module import *

然而,这样的语句会导入哪些文件取决于操作系统的文件系统。所以我们在__init__.py 中加入 __all__ 变量。该变量包含执行这样的语句时应该导入的模块的名字。它由一个模块名字符串列表组成.。

2. __all__

Pythonmoudle是很重要的一个概念moudle里一般都会有一个__init__.py文件。有的__init__.py中是空白,有的却会有__all__参数

如果其他页面import 的时候,如果__init__.py是空白的,可以直接importmoudle的所有函数。而如果__init__.py中定义了__all__,则import 的时候只会导入__all__部分定义的内容

例如,我们可以这样组织一个package:

package1/
    __init__.py
    subPack1/
        __init__.py
        module_11.py
        module_12.py
        module_13.py
    subPack2/
        __init__.py
        module_21.py
        module_22.py

__init__.py可以为空,只要它存在,就表明此目录应被作为一个package处理

当然,__init__.py中也可以设置相应的内容现在我们在module_11.py中定义一个函数:

def funA():

print "funcA in module_11"

在顶层目录(也就是package1所在的目录,当然也参考上面的介绍,将package1放在解释器能够搜索到的地方)运行python:

>>>from package1.subPack1.module_11 import funcA

>>>funcA()

funcA in module_11

这样,我们就按照package的层次关系,正确调用了module_11中的函数。

细心的同学会发现,有时在import语句中会出现通配符*,导入某个module中的所有元素,这是怎么实现的呢?

答案就在__init__.py中。我们在subPack1__init__.py文件中写

__all__ = ['module_13', 'module_12']

然后进入python

>>>from package1.subPack1 import *

>>>module_11.funcA()

Traceback (most recent call last):

File "", line 1, in

ImportError: No module named module_11

也就是说,以*导入时,package内的module是受__init__.py限制的

 

模块发布

1.mymodule目录结构体如下:

.
├── setup.py
├── suba
│   ├── aa.py
│   ├── bb.py
│   └── __init__.py
└── subb
    ├── cc.py
    ├── dd.py
    └── __init__.py

2.编写setup.py,py_modules需指明所需包含的py文件

from distutils.core import setup

setup(name="xwp", version="1.0", description="xwp's module", author="FLY", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])

3.构建模块

python setup.py build

构建后目录结构

.
├── build
│   └── lib.linux-i686-2.7
│       ├── suba
│       │   ├── aa.py
│       │   ├── bb.py
│       │   └── __init__.py
│       └── subb
│           ├── cc.py
│           ├── dd.py
│           └── __init__.py
├── setup.py
├── suba
│   ├── aa.py
│   ├── bb.py
│   └── __init__.py
└── subb
    ├── cc.py
    ├── dd.py
    └── __init__.py

4.生成发布压缩包

python setup.py sdist

打包后,生成最终发布压缩包xwp-1.0.tar.gz , 目录结构

.
├── build
│   └── lib.linux-i686-2.7
│       ├── suba
│       │   ├── aa.py
│       │   ├── bb.py
│       │   └── __init__.py
│       └── subb
│           ├── cc.py
│           ├── dd.py
│           └── __init__.py
├── dist
│   └── xwp-1.0.tar.gz
├── MANIFEST
├── setup.py
├── suba
│   ├── aa.py
│   ├── bb.py
│   └── __init__.py
└── subb
    ├── cc.py
    ├── dd.py
    └── __init__.py

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试