Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4056717
  • 博文数量: 272
  • 博客积分: 7846
  • 博客等级: 少将
  • 技术积分: 6476
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-25 16:27
文章分类

全部博文(272)

分类: Python/Ruby

2012-11-28 16:30:08

   
    Python文件操作是Python编程的基础,其实不难和C语言很像。内容无非分为几大块:
  • 新建文件/目录
  • 删除文件/目录
  • 使用文件/得到目录
  • 复制/移动文件
  • 判断文件/目录
  • 获得文件信息
    此外,还有目录内容列表、路径操作、文件合并操作等。请注意,我使用的版本是3.3现在言归正传:

0、前提
    所有后续操作,应该先导入os模块(os是小写),即:


  1. import os

1、新建文件/目录
    (1)创建文件
    第一种方法是使用os模块内置方法mknod创建节点,mkfilo是创建管道。但是3.3版本下,我尝试用它来创建空文件,失败:


  1. >>> import os
  2. >>> mknod('newfile')
  3. Traceback (most recent call last):
  4.   File "", line 1, in <module>
  5.     mknod('newfile')
  6. NameError: name 'mknod' is not defined
  7. >>> os.mknod('newfile')
  8. Traceback (most recent call last):
  9.   File "", line 1, in <module>
  10.     os.mknod('newfile')
  11. AttributeError: 'module' object has no attribute 'mknod'

    我不知道是因为什么原因,在网上查找也没有结果。我将去CU论坛里求助,有了结果会尽快更新博客的。大家要是知道的话,可以直接回复本文。

    感谢yk325我的启发。

    第二种方式,比较常用。和C一样,参数都一样
    open("test.txt",w),该方法将直接打开一个文件,如果文件不存在则创建文件
    关于open 模式:
    w写打开
    a追加打开(从 EOF 开始, 必要时创建新文件)
    r:读打开,如果open("this.txt")这种写法,默认就是r
    r+:读写打开
    w+:读写打开
    a+:读写打开
    rb、wbab:二进制模式
    rb+、wb+、ab+:二进制读写模式打开


    (2)创建目录
    如果知道父目录,只是在其下创建一个子目录的话,容易:


  1. >>> os.mkdir(r"C:\Users\lk\Desktop\python\No1")
     如果想同时新建多层目录,就需要使用makedirs,比如:

  1. >>> os.makedirs(r"C:\Users\lk\Desktop\python\No1\No2\No3\No4")
    需要格外注意:mkdir(正确) != mkdirs(错误) != makedirs(正确)

2、删除文件/目录
    (1)删除文件
    删除文件使用的是os.remove(不是move),如下例所示


  1. >>> os.remove(r"C:\Users\lk\Desktop\python\test3.txt")
  2. >>> os.remove(r"C:\Users\lk\Desktop\python\No1")
  3. Traceback (most recent call last):
  4.   File "", line 1, in <module>
  5.     os.remove(r"C:\Users\lk\Desktop\python\No1")
  6. PermissionError: [WinError 5] 拒绝访问。: 'C:\\Users\\lk\\Desktop\\python\\No1'

    使用remove删除文件,不论文件是否为空都可以。但它不能用来删除目录,否则拒绝访问。
    (2)删除目录
    删除空目录,使用rmdir。当然你肯定不过瘾,怎样全删呢,不管有多少个子目录,里面又含有多少文件,用rmtree搞定。想使用rmtree,它并不在os标准包中,所以还需要shutil包


  1. >>> os.rmdir(r"C:\Users\lk\Desktop\python\No1\No2\No3\No4")
  2. >>> import shutil
  3. >>> shutil.rmtree(r"C:\Users\lk\Desktop\python\No1")


3、使用文件/进入目录
    (1)使用文件
    这里使用的意思是读取、写入和追加
    先来看读是的没错,在家吃冰箱里的冷饮前提是家里首先要有冰箱。前需要确保文件已经打开,然后使用read()、readline()、readlines()方法即可,区别在于readline()
将从当前位置读取一行并以“/n”结尾(麻烦的是很多行末已经是“/n”结尾罗,所以可以预想,将产生很多空行,readlines()接着没读完的读完,负责把剩下的内容全部一次性读出来组成字符串列表返回,而read()则从头到尾整体读出到一个长长的字符串中
    再来看写,写很简单,用write()写入就可以罗。写完了可以close关闭文件,内容便保存起来了。


  1. >>> myfile = open(r"C:\Users\lk\Desktop\python\Test.txt",'w+')
  2. >>> myfile.write("""
  3. 五岳之巅

  4. 滚雷执闪劈裂天,
  5. 怒对风狂山涧间。
  6. 脚踩神魔百尺潭,
  7. 头举妖仙万韧山。

  8. 荆棘塞途奈我何,
  9. 断崖绝路又何难?
  10. 有朝一日登高处,
  11. 万卷浮云任尔翻。
  12. """)
  13. 80
  14. >>> myfile.close()
  15. >>> myfile = open(r"C:\Users\lk\Desktop\python\Test.txt",'r')
  16. >>> myfile.readline()
  17. '\n'
  18. >>> myfile.readline()
  19. '五岳之巅\n'
  20. >>> myfile.readlines()
  21. ['\n', '滚雷执闪劈裂天,\n', '怒对风狂山涧间。\n', '脚踩神魔百尺潭,\n', '头举妖仙万韧山。\n', '\n', '荆棘塞途奈我何,\n', '断崖绝路又何难?\n', '有朝一日登高处,\n', '万卷浮云任尔翻。\n']
  22. >>> myfile.seek(0,0)
  23. 0
  24. >>> myfile.read()
  25. '\n五岳之巅\n\n滚雷执闪劈裂天,\n怒对风狂山涧间。\n脚踩神魔百尺潭,\n头举妖仙万韧山。\n\n荆棘塞途奈我何,\n断崖绝路又何难?\n有朝一日登高处,\n万卷浮云任尔翻。\n'
    有个想法,要实验一下,如何定位使本诗变为两句一行的形式?我是这样想的,2-3合并,4-5合并,...以此类推。合并要把偶数行尾的“\n”弄掉现在文件里面是这个样子的:
    两种解决方案:
    第一种,笨办法,打开文件,每次读一行,遇到2-3/4-5就删一个“\n”:


  1. import os
  2. f = open(r"C:\Users\lk\Desktop\python\Test.txt",'r')
  3. h = open(r"C:\Users\lk\Desktop\python\Result.txt",'w+')

  4. #i为行号变量
  5. i = 1
  6. #j为修改类型,1为删除,0为不变
  7. j = [1,1,0,1,0,1,0,0,1,0,1,0,1,0]

  8. for i in range(0,len(j)):
  9.     s = f.readline()
  10.     if j[i]:
  11.         s = s[:-1]
  12.     h.write(s)
  13.     i = i + 1

  14. f.close()
  15. #重新读取j
  16. h.seek(0,0)
  17. h.read()
  18. h.close()
    其中,s = s[:-1]这个用法非常好,要不是为了这个,谁会用如此麻烦的方式完成程序?结果如下:

    第二种,搜“,”,逗号下一个“\n”删之即可。这个方法很好,简单,高效。哈哈。


  1. import os
  2. f = open(r"C:\Users\lk\Desktop\python\Test.txt",'r')
  3. h = open(r"C:\Users\lk\Desktop\python\Result.txt",'w+')

  4. str = f.read()
  5. s = str.split(',')

  6. str = s[0][1:]

  7. for i in range(1,len(s)):
  8.     str = str +','+ s[i][1:]
  9.     i = i + 1

  10. h.write(str)

  11. f.close()
  12. h.close()
    可以看出,这种方法代码不多。
    最后还有个追加问题,追加的方法是用open(xxx,'a')来控制,用a打开的文件默认就是seek(2,0)游标处于文件尾。还是举例:

  1. import os
  2. f = open(r"C:\Users\lk\Desktop\python\Result.txt",'a+')

  3. str = "\n作者:五岳之巅,2011年1月14日,13点于榴花\n"

  4. f.write(str)

  5. f.close()
    结果如下图:

    最近我在看《数学之美》这本书,我在想对于每一行我们可以使用len(readline())进行测量并统计,不过真实世界中经常是整段统计,是按自然段落统计而非行统计,搜索引擎就是这样,对于不同位置的段还赋予不同的权重,比如第一自然段和最后一自然段权重较高。
    我的问题是如何用Python简单地统计一篇文章段落的词数?
    要解决的关键问题就只有一个,即“什么是段落?”答:必须满足连续文字前后两个“\n”之间的就是段落。于是我写了如下的代码,也赶了个时髦,统计莫言《》的第一部第一章的自然段,并输出统计内容。原文如下:


    使用如下代码:

  1. import os
  2. f = open(r"C:\Users\lk\Desktop\python\wa.txt",'r')

  3. #r保存结果
  4. r = {}

  5. paper = (f.read()).split('\n\n')
  6. num = 1

  7. for i in paper:
  8.     r[num] = len(i)
  9.     num = num + 1

  10. f.close()

  11. #range(1,num)是不包含num的
  12. for key in range(1,num):
  13.     print("第%s自然段:共有%d个字\n"%(key,r[key]))
    得到如下结果:

  1. >>>
  2. 第1自然段:共有250个字

  3. 第2自然段:共有130个字

  4. 第3自然段:共有2566个字

  5. 第4自然段:共有409个字

  6. 第5自然段:共有87个字
    好了,到这里已经做出了一个简易的段落字数统计,下一步还可以深入做下去,比如我想知道这一章主要讲的什么,怎么办?没错,那就得分析词频了,最近看到一款“结巴分词”软件,是专门针对Python的,当然可以拿来用,有了中文分词,可以干太多的事。但这就是后话了,不再本文中出现罗。


    (2)得到目录
    访问目录的操作主要是获得指定目录及从文件路径中得到相关信息
    对目录进行操作,Python把这些功能都封装到path模块中,对于不同的操作系统Python可以使用相同的方法,这便使得程序移植变得更加容易

    了解os.path模块,要从了解当前目录名和文件名入手,这分为两种情况:
    1)已知一个目录
    如果给定一个目录,那么我们可以使用os.path.basename()方法获得文件名,而使用os.path.dirname()获取文件前的路径。


  1. >>> import os.path
  2. >>> filepath = r'C:\Users\lk\Desktop\Python编程入门经典.pdf'
  3. >>> os.path.basename(filepath)
  4. 'Python编程入门经典.pdf'
  5. >>> os.path.dirname(filepath)
  6. 'C:\\Users\\lk\\Desktop'

    OK,接下来是几种常用用法,splitdrive()取得根目录或磁盘盘符(操作系统而定,Linux下我还没试,不知道是不是),split()分解出路径和文件全名,这时可用许多变量分别存储返回的元组中相对应的值,splitext()也是拆分并返回元组,但它最后一个值不是文件名而是文件扩展名。

  1. >>> os.path.splitdrive(filepath)
  2. ('C:', '\\Users\\lk\\Desktop\\Python编程入门经典.pdf')
  3. >>> os.path.splitdrive('/home/lk/document/ok.py')
  4. ('', '/home/lk/document/ok.py')
  5. >>> os.path.split(filepath)
  6. ('C:\\Users\\lk\\Desktop', 'Python编程入门经典.pdf')
  7. >>> a,b = os.path.split(filepath)
  8. >>> print(a)
  9. C:\Users\lk\Desktop
  10. >>> print(b)
  11. Python编程入门经典.pdf
  12. >>> a,b = os.path.splitext(filepath)
  13. >>> print(a)
  14. C:\Users\lk\Desktop\Python编程入门经典
  15. >>> print(b)
  16. .pdf

    2)得到当前目录
    如果现在你不知道你当前执行程序的路径在哪里该怎么办?好办,Python的os模块自带了getcwd()。准备no1.py文件:
    在终端执行os.getcwd(),随后执行程序no1.py,请看结果:

  1. >>> os.getcwd()
  2. 'C:\\Python33'
  3. >>> ================================ RESTART ================================
  4. >>>
  5. 程序no1.py当前路径是:C:\Users\lk\Desktop\python
  6. >>>

   (3)访问目录
    访问目录的操作主要是进入目录、跳出目录和列出当前目录内容
    进入、跳出目录,并非像OS Shell那样与人交互,使用cd命令进入某层目录。获取目录中的内容使用os.listdir()。
接着刚才的例子:

  1. >>>
  2. 程序no1.py当前路径是:C:\Users\lk\Desktop\python
  3. >>> os.listdir()
  4. ['blogtest.py', 'chapter8.py', 'mydoc.docx', 'no1.py', 'no2.py', 'no3.py', 'no4.py', 'no5.py', 'qewqeq.txt', 'Result.txt', 'temp.txt', 'Test.txt', 'test2.txt', 'wa.txt']
  5. >>> os.mkdir('newdir')
  6. >>> os.listdir()
  7. ['blogtest.py', 'chapter8.py', 'mydoc.docx', 'newdir', 'no1.py', 'no2.py', 'no3.py', 'no4.py', 'no5.py', 'qewqeq.txt', 'Result.txt', 'temp.txt', 'Test.txt', 'test2.txt', 'wa.txt']
    从新建的newdir文件夹事实中可以看出,是有相对路径滴!
    那么目录如何合成呢?很容易,目录就是字符串,合成目录就是合成字符串,可以使用os.path.join:

  1. >>> os.getcwd()
  2. 'C:\\Users\\lk\\Desktop\\python'
  3. >>> a,b = os.path.split(os.getcwd())
  4. >>> print(a)
  5. C:\Users\lk\Desktop
  6. >>> print(b)
  7. python
  8. >>> c = "论文"
  9. >>> otherdir = os.path.join(a,c)
  10. >>> os.listdir(otherdir)
  11. ['_云计算_下的图书馆发展策略研究.kdh', '云计算XaaS概念簇的层次模型研究.doc', '云计算_图书馆事业发展的机遇与挑战.kdh', '从OCLC看图书馆云计算的未来.kdh', '博士', '基于云计算的图书馆IT应用探讨.kdh', '基于云计算的图书馆信息平台的构建.caj', '已读', '情报学报.xls', '我国云计算和图书馆相关问题研究综述.caj']

   (4改变目录
    现在来看看如何改变目录,前面说过了python的os.getcwd()获取当前工作目录,即当前python脚本工作的目录路径。
    而os.chdir()则用来改变当前脚本工作目录,os.curdir用于返回当前目录,值得一提的是
os.pardir用以获取当前目录的父目录字符串名。试试吧:

  1. >>> os.curdir
  2. '.'
  3. >>> os.path.pardir
  4. '..'
  5. >>> os.chdir(r'd:/')
  6. >>> os.listdir()
  7. ['$RECYCLE.BIN', '123', '360Downloads', 'Boot', 'bootmgr', 'BOOTSECT.BAK', 'foiu.ld', 'FSGLD', 'grldr', 'Media', 'Program Files', 'System Volume Information']
  8. >>>


4递归目录
    现在来看看如何改变目,使用递归让自己解决自己的问题:


  1. import os

  2. def dir_tree(dir_path):
  3.     if not os.path.isdir(dir_path):
  4.         print("%s是非法目录"%(dir_path))
  5.         return False
  6.     for name in os.listdir(dir_path):
  7.         fullpath = os.path.join(dir_path,name)
  8.         print(fullpath)
  9.         if os.path.isdir(fullpath):
  10.             dir_tree(fullpath)

  11. a = r"C:\Users\lk\Desktop\python"
  12. dir_tree(a)
    结果如下:

  1. >>>
  2. C:\Users\lk\Desktop\python\blogtest.py
  3. C:\Users\lk\Desktop\python\chapter8.py
  4. C:\Users\lk\Desktop\python\mydoc.docx
  5. C:\Users\lk\Desktop\python\newdir
  6. C:\Users\lk\Desktop\python\no1.py
  7. C:\Users\lk\Desktop\python\no2.py
  8. C:\Users\lk\Desktop\python\no3.py
  9. C:\Users\lk\Desktop\python\no4.py
  10. C:\Users\lk\Desktop\python\no5.py
  11. C:\Users\lk\Desktop\python\no6.py
  12. C:\Users\lk\Desktop\python\no7.py
  13. C:\Users\lk\Desktop\python\qewqeq.txt
  14. C:\Users\lk\Desktop\python\Result.txt
  15. C:\Users\lk\Desktop\python\temp.txt
  16. C:\Users\lk\Desktop\python\Test.txt
  17. C:\Users\lk\Desktop\python\test2.txt
  18. C:\Users\lk\Desktop\python\top
  19. C:\Users\lk\Desktop\python\top\middle
  20. C:\Users\lk\Desktop\python\top\middle\bottom
  21. C:\Users\lk\Desktop\python\top\middle\bottom\bottom.txt
  22. C:\Users\lk\Desktop\python\top\middle.txt
  23. C:\Users\lk\Desktop\python\wa.txt
  24. >>>

4复制/移动文件
    python中,移动、复制、重命名一个文件/文件夹是通过shutil模块实现的,在这里结合目录操作,一个综合的例子:


  1. import os
  2. import shutil

  3. cpath = os.getcwd() #current path

  4. os.makedirs("top/middle/bottom")
  5. mpath = os.path.join(cpath,"top/middle/bottom") #modified path

  6. if os.path.isdir(mpath):
  7.     os.chdir(mpath)
  8.     fname = "bottom.txt"
  9.     fpath = os.path.join(mpath,fname)
  10.     f = open(fpath,'w')
  11.     f.write('this is the end line.')
  12.     f.close()

  13. if os.path.isfile(fpath):
  14.     shutil.copy(fname,os.path.pardir)
  15.     os.chdir(os.path.pardir)
  16.     shutil.move(fname,"middle.txt")
  17.     fname = "middle.txt"
  18.     fpath = os.path.join(os.getcwd(),fname)
  19.     f = open(fpath,'r+')
  20.     tmpwords = f.read()
  21.     f.seek(0,0)
  22.     f.write("this is the second line.\n"+tmpwords)
  23.     f.close()
  24.     shutil.move(fpath,os.path.pardir)


5判断文件/目录
    以下内容返回值True,False
    exists()    指定路径(文件或者目录)是否存在
    isabs()     指定路径是否为绝对路径
    isdir()     指定路径是否存在且为一个目录
    isfile()    指定路径是否存在且为一个文件
    samefile()  两个路径名是否指向同一个文件

  1. >>> os.listdir(otherdir)
  2. ['_云计算_下的图书馆发展策略研究.kdh', '云计算XaaS概念簇的层次模型研究.doc', '云计算_图书馆事业发展的机遇与挑战.kdh', '从OCLC看图书馆云计算的未来.kdh', '博士', '基于云计算的图书馆IT应用探讨.kdh', '基于云计算的图书馆信息平台的构建.caj', '已读', '情报学报.xls', '我国云计算和图书馆相关问题研究综述.caj']
  3. >>> os.path.exists(otherdir)
  4. True
  5. >>> os.path.isdir(otherdir+'noname')
  6. False
  7. >>> os.path.isfile(otherdir+'基于云计算的图书馆信息平台的构建.caj')
  8. False
  9. >>> os.path.isfile(os.path.join(otherdir,'基于云计算的图书馆信息平台的构建.caj'))
  10. True
  11. >>>
    非常有趣的是最后两处,只用使用os.path.join()把目录和文件名组合,才能构成合法路径。哈哈。


6获得文件信息
    使用以下方法获取文件相关信息:
    getatime()    返回最近访问时间(浮点型秒数)
    getctime()    返回文件创建时间
    getmtime()    返回最近文件修改时间
    getsize()     返回文件大小(字节为单位)
    abspath()     返回绝对路径


  1. >>> filepath = os.path.join(otherdir,'基于云计算的图书馆信息平台的构建.caj')
  2. >>> os.path.isfile(filepath)
  3. True
  4. >>> os.path.getatime(filepath)
  5. 1345895347.7942
  6. >>> os.path.getctime(filepath)
  7. 1345895347.7942
  8. >>> os.path.getsize(filepath)
  9. 319364
  10. >>> print("%dKB"%(os.path.getsize(filepath)/1024))
  11. 311KB
  12. >>> os.path.abspath(filepath)
  13. 'C:\\Users\\lk\\Desktop\\论文\\基于云计算的图书馆信息平台的构建.caj'

    五岳之巅原创,如有转载,必须注明出处,谢谢!


阅读(18675) | 评论(3) | 转发(3) |
给主人留下些什么吧!~~

矮油那个喂2013-04-23 15:09:01

你好,我是一名本科生,最近正在搞学习python,但是在运用的时候出现了一些问题,看到你写的python白手起家,于是想问你几个问题:
1.我现在在用llfuse写一个文件系统,由于官网上有一个example的代码,我正打算对那个代码进行改造,我想模拟云服务,当我在文件系统这边操作的时候我的“云”(实际是一个存在磁盘上的文件夹)中也会有相应的回应,比如说增加文件,等等,我在看llfuse的源代码的时候,发现那里面都是用node来创建的,是否意味着我要使云端也有相应回应的时候,那边也需要用node作为参数呢?
2.非常小白的问题,我不知道怎样获得一个已有文件/文件夹的node,我在网上搜到了一些函数,可是在linux下没有成功。举个例子,我看到用File()这个函数可以查看文件的节点,可是我输入的时候,终端总是报错,说File没有定义。我不知道具体到底用什么。。。
大神,求救啊!!
PS:我是女生

五岳之巅2012-11-29 22:25:41

yk325: mknod是用来创建设备节点的,主要是用于/dev目录下的设备节点,创建的时候需要提供主设备号与次设备号,一个节点就对应于一个特定功能的设备

虽然在Linux里面设.....
说得好,原理就是这样。我在Win7下没有试验成功的主要原因,应该就在于windows无法创建node,文件系统和Linux不一样。但我想,在Linux下mknode是可以创建新文件的。对吧?

yk3252012-11-29 21:00:30

mknod是用来创建设备节点的,主要是用于/dev目录下的设备节点,创建的时候需要提供主设备号与次设备号,一个节点就对应于一个特定功能的设备

虽然在Linux里面设备也对应于一个文件,但用它来创建文件根本上就是错误的