它确实是那个内置模块, 然而我深信, 许多朋友对于它的具体情形是完全陌生的。在当下这个时间段里, 我把那个内置模块的所有一切使用方法以及所能提供的功能进行了一个非常细致的解析和说明, 并且同时列举了一系列在实际操作中非常具有实用价值的典型案例, 这些内容的提供, 对于那些想要加深理解或者顺利使用的群体来说, 完全可以做到没有障碍和困难。1. 从标准的输入里面, 把数据给读取出来。当你的脚本没有传入任何参数的情况存在时, 默认会以下面这种方式运作, 那就是将标准输入, 也就是简称为stdin的那个东西, 当作是输入的来源来使用。# demo.pyimport fileinputfor line in fileinput.input():print(line)效果显示是这样的, 不论你输入了什么内容, 程序都会进行自动读取, 然后再把它打印输出一次, 看起来就像一个复读机一样。$ python demo.pyhellohellopythonpython2. 把这个文件单独地打开来。你可以单独去打开某个文件, 那么操作起来就特别简单啦, 你只需要在 files 这个地方去输入文件名就完事了。import fileinputwith fileinput.input(files(a.txt,)) as file:for line in file:print(f{fileinput.filename()} 第{fileinput.lineno()}行: {line}, end)其中, a.txt 这个文件里的内容是这样的。helloworld执行之后, 就会出现以下那样的输出。$ python demo.pya.txt 第1行: helloa.txt 第2行: world需要向大家解释清楚的是一个基本情况, 那就是.input()这个函数在默认的情况下, 它会使用mode等于rd这种模式去读取文件内容, 但是如果你的文件本身是二进制的文件格式, 那么你就应该去使用mode等于rb这种模式来进行操作了, 整个体系中存在的读取模式非常明确, 就是只有上述提到的那两种情况。3. 把多个文件全都打开, 让一个一个的文件都呈现出来。从上面那个例子我们也能够看出来, 我在那个input函数里面传入了files这个参数, 它接收的是一个包含好几个文件名的列表或者元组, 如果传入一个的话就是读取一个文件, 如果传入多个的话就是读取多个文件。import fileinputwith fileinput.input(files(a.txt, b.txt)) as file:for line in file:print(f{fileinput.filename()} 第{fileinput.lineno()}行: {line}, end)a.关于那个名字为 txt的文件, 以及另一个名为 b.txt的文件, 这两者的具体内容, 实际上分别展现的是什么呢。$ cat a.txthelloworld$ cat b.txthellopython程序执行完毕之后, 输出的结果展示在下面这一部分内容里。因为原本存在于 a.txt 以及 b.txt 里面的数据内容, 都被合并到了一个单独的文件名为 file 的对象里面去。所以这里关于 .() 这个方法调用行为的表现情况就是, 它仅仅只针对那些只读取了单个文件的场景来说明了状况。在这种情况下得到的行号数字, 才是确实属于原文件中真实位置的行号数值。$ python demo.pya.txt 第1行: helloa.txt 第2行: worldb.txt 第3行: hellob.txt 第4行: python想要在进行多文件读取操作的时候, 也去获取到原文件里的真实行号信息, 是可以使用括号加点的这种调用方式的。import fileinputwith fileinput.input(files(a.txt, b.txt)) as file:for line in file:print(f{fileinput.filename()} 第{fileinput.filelineno()}行: {line}, end)运行后输出如下$ python demo.pya.txt 第1行: helloa.txt 第2行: worldb.txt 第1行: hellob.txt 第2行: python这种使用方法与 glob 模块搭配起来, 二者之间的关系简直就是堪称绝配。import fileinputimport globfor line in fileinput.input(glob.glob(*.txt)):if fileinput.isfirstline():print(-*20, fReading {fileinput.filename()}..., -*20)print(str(fileinput.lineno()) : line.upper(), end)程序的运行效果展示在下文中。$ python demo.py-------------------- Reading b.txt... --------------------1: HELLO2: PYTHON-------------------- Reading a.txt... --------------------3: HELLO4: WORLD4. 在读取的过程当中, 还要把文件给备份下来。对于 .input 来说, 它存在一个特定的参数, 借助该参数, 用户能够明确指定所要采用的备份文件后缀名情形, 例如 .bak。import fileinputwith fileinput.input(files(a.txt,), backup.bak) as file:for line in file:print(f{fileinput.filename()} 第{fileinput.lineno()}行: {line}, end)运行的结果是这样的, 它会多出一个文件, 这个文件的名字叫做 a.txt.bak。$ ls -l a.txt*-rw-r--r-- 1 MING staff 12 2 27 10:43 a.txt$ python demo.pya.txt 第1行: helloa.txt 第2行: world$ ls -l a.txt*-rw-r--r-- 1 MING staff 12 2 27 10:43 a.txt-rw-r--r-- 1 MING staff 42 2 27 10:39 a.txt.bak5. 标准输出通过重定向机制来完成替换。输入文件包含一个参数, 该参数用于表明需不需要将标准输出端产生的结果写入到对应的文件以内去, 在不进行其他设定的情况下, 默认的状态是不会对原有内容进行覆盖替换操作的。请您看一看, 下面有这样的一段代码, 它是用来进行测试的。import fileinputwith fileinput.input(files(a.txt,), inplaceTrue) as file:print([INFO] task is started...)for line in file:print(f{fileinput.filename()} 第{fileinput.lineno()}行: {line}, end)print([INFO] task is closed...)程序在运行之后, 大家会发觉, 在 for 循环体里面的 print 内容, 会重新写入原文件中。与此同时, 放在 for 循环体外面的 print, 则没有出现任何变化。$ cat a.txthelloworld$ python demo.py[INFO] task is started...[INFO] task is closed...$ cat a.txta.txt 第1行: helloa.txt 第2行: world通过这个机制, 可以很容易地实现文本替换功能。import sysimport fileinputfor line in fileinput.input(files(a.txt, ), inplaceTrue):#将Windows/DOS格式下的文本文件转为Linux的文件if line[-2:] \r\n:line line \nsys.stdout.write(line)附如何实现 DOS 和 UNIX 格式互换以供程序测试使用 vim 输入如下指令即可DOS转UNIX:setfileformatunixUNIX转DOS:setfileformatdos6. 这种方法, 是不得不向大家来介绍的一个方法。假如说我们仅仅是想要把它拿来充当用来代替那一种叫做 open 的, 去进行读取文件操作的一个工具的话, 那么上面讲的那些内容, 就完全足以达成满足你那个想要的要求了。返回当前正在被读取的文件的名称。当第一行的数据尚未被读取的时候, 这个时候会返回 None。返回表示当前文件描述符的整数值, 在文件未打开且位置处于首行之前的时候, 会返回 -1。返回已经被读取过的行数的累计总数, 当第一行的文本还没有被读到的时候, 返回的是数字 0, 等到了最后一个文件的最后一行也被读过之后, 就返回那一行的具体行号。返回当前文件内部的行号信息。如果尚未开始读取第一行的内容, 那么系统会返回值是数字 0。当最后一个文件的最后一行被完成读取之后, 系统将返回位于此文件内部的具体那一行的行号值。可是, 如果打算去实现一些更加复杂的逻辑过程的话, 那么你大概是需要来使用以下提到的这些特定方法的这一点情况。在刚读取的该行是当前所在文件的第一行这个前提之下则返回True这个结果, 如果不是这种情况的话则返回False。如果最后读取的行来自sys.stdin, 则返回True, 否则返回False。把当前这个文件关了, 好让下回迭代能接着去读下一个文件的第一行, 要是真有下一个文件的话先前那个文件里那些没被算进去的行数, 这回也不往后累计了。一直到把下一个文件的首行取过来之后, 文件名那部分才跟着变样在头一行还没进来的时候, 这项功能是启动不了的它压根儿就不能用来把开头的第一个文件给溜过去。到头最后一个文件的最后一趟也读完了的时候, 这么个玩意儿就不管使了。把序列给关掉了。7. 进阶一点的玩法在使用 .input() 这个函数的时候, 其中包含了有一个参数, 该参数能够支持用户来将自己自定义的对象读取方法传进去。要是说你并没有去传递任何的那种植入点函数, 那系统它会自动地就是使用那个叫做的打开的函数来作为一种默认的选项。我们特意为大家提供了两种类型的勾子, 以便供你选择和使用。使用 gzip 和 bz2 模块透明地打开 gzip 和 bzip2 压缩的文件通过扩展名 .gz 和 .bz2 来识别。如果文件扩展名不是 .gz 或 .bz2文件会以正常方式打开即使用 open() 并且不带任何解压操作。使用示例: fi .(.)返回一个钩子, 这个钩子用来打开每个文件, 使用的是给定的编码和错误参数方法来读取文件。使用示例包括这样的代码行: fi变量被赋予了一个通过open方法创建的对象, 其中open方法的第一个参数是文件名, 第二个参数指定编码方式为utf-8, 第三个参数指定错误处理方式为空字符串。如果你自己的场景比较特殊, 以上的三种勾子都不能满足你的要求, 你也可以自定义。我在这里举例说明, 以引出更多高明的见解或方法。如果用户想要通过使用某种方式来读取网络上的文件, 可以这样去定义一个钩子。def online_open(url, mode):import requestsr requests.get(url)filename url.split(/)[-1]with open(filename,w) as f1:f1.write(r.content.decode(utf-8))f2 open(filename,r)return f2你可以将这个函数直接进行传递, 并且传递给那个已经存在的对象或者环境。import fileinputfile_url https://www.csdn.net/robots.txtwith fileinput.input(files(file_url,), openhookonline_open) as file:for line in file:print(line, end)在程序启动并执行完成以后, 结果和我们最初想象的情况是完全一致的, 此时CSDN所关联的那个文件的具体内容就被顺利地呈现到了输出界面之中。User-agent: *Disallow: /scriptsDisallow: /publicDisallow: /css/Disallow: /images/Disallow: /content/Disallow: /ui/Disallow: /js/Disallow: /scripts/Disallow: /article_preview.html*Disallow: /tag/Disallow: /*?*Disallow: /link/Sitemap: https://www.csdn.net/sitemap-aggpage-index.xmlSitemap: https://www.csdn.net/article/sitemap.txt8. 请你来举一点在实际应用中确实有用的那些具体的例子。案例一的这种情况, 需要读取一个文件的所有行。import fileinputfor line in fileinput.input(data.txt):print(line, end)在案例二当中, 我们要做的事儿是去读取多个文件里面所有的行。import fileinputimport globfor line in fileinput.input(glob.glob(*.txt)):if fileinput.isfirstline():print(-*20, fReading {fileinput.filename()}..., -*20)print(str(fileinput.lineno()) : line.upper(), end)这里是案例三的情况, 在这个案例里边的操作是利用一种方式, 就是把这个CRLF文件转变成LF格式。import sysimport fileinputfor line in fileinput.input(files(a.txt, ), inplaceTrue):#将Windows/DOS格式下的文本文件转为Linux的文件if line[-2:] \r\n:line line \nsys.stdout.write(line)案例四是用配合使用 re 来对日志进行分析获取所有内容中包含日期的那些行。#--样本文件--error.logaaa1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough...bbb1970-01-02 10:20:30 Error: **** Due to System Out of Memory...ccc#---测试脚本---import reimport fileinputimport syspattern \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}for line in fileinput.input(error.log,backup.bak,inplace1):if re.search(pattern,line):sys.stdout.write( )sys.stdout.write(line)#---测试结果--- 1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough... 1970-01-02 10:20:30 Error: **** Due to System Out of Memory...案例五利用实现类似于grep的功能import sysimport reimport fileinputpattern re.compile(sys.argv[1])for line in fileinput.input(sys.argv[2]):if pattern.match(line):print(fileinput.filename(), fileinput.filelineno(), line)$ ./demo.py import.*re *.py#查找所有py文件中含import re字样的addressBook.py 2 import readdressBook1.py 10 import readdressBook2.py 18 import retest.py 238 import re9. 在此处, 作为结束的部分来进行书写。这是对 open 函数的再次封装, 在只需要读取数据的情况下, 它明显比 open 表现得更有专业度, 也更符合人的使用习惯, 虽然在那些带有写操作的复杂场景里, 它就没办法发挥作用了, 从它的命名也能看出来, 这个模块就是专门负责输入也就是读的, 而不是负责输出也就是写的。
阅读完成 · 觉得有帮助?