python 使用fileinput读取文件

fileinput 是 Python 的内置模块,但我相信,不少人对它都是陌生的。今天我把 fileinput 的所有的用法、功能进行详细的讲解,并列举了一些非常实用的案例,对于理解和使用它可以说完全没有问题。

1. 从标准输入中读取

当你的 Python 脚本没有传入任何参数时,fileinput 默认会以 stdin 作为输入源

# demo.py
import fileinput

for line in fileinput.input():
    print(line) 

效果如下,不管你输入什么,程序会自动读取并再打印一次,像个复读机似的。

$ python demo.py 
hello
hello

python
python

2. 单独打开一个文件

单独打开一个文件,只需要在 files 中输入一个文件名即可

import fileinput

with fileinput.input(files=('a.txt',)) as file:
    for line in file:
        print(f'{fileinput.filename()} 第{fileinput.lineno()}行: {line}', end='') 

其中 a.txt 的内容如下

hello
world

执行后就会输出如下

$ python demo.py
a.txt 第1行: hello
a.txt 第2行: world

需要说明的一点是,fileinput.input() 默认使用 mode='r' 的模式读取文件,如果你的文件是二进制的,可以使用mode='rb' 模式。fileinput 有且仅有这两种读取模式。

3. 批量打开多个文件

从上面的例子也可以看到,我在 fileinput.input 函数中传入了 files 参数,它接收一个包含多个文件名的列表或元组,传入一个就是读取一个文件,传入多件就是读取多个文件。

import fileinput

with 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.txt
hello
world
$ cat b.txt
hello
python

运行后输出结果如下,由于 a.txt 和 b.txt 的内容被整合成一个文件对象 file ,因此 fileinput.lineno() 只有在读取一个文件时,才是原文件中真实的行号。

$ python demo.py
a.txt 第1行: hello
a.txt 第2行: world
b.txt 第3行: hello
b.txt 第4行: python

如果想要在读取多个文件的时候,也能读取原文件的真实行号,可以使用 fileinput.filelineno() 方法

import fileinput

with fileinput.input(files=('a.txt', 'b.txt')) as file:
    for line in file:
        print(f'{fileinput.filename()} 第{fileinput.filelineno()}行: {line}', end='')

运行后,输出如下

$ python demo.py
a.txt 第1行: hello
a.txt 第2行: world
b.txt 第1行: hello
b.txt 第2行: python

这个用法和 glob 模块简直是绝配

import fileinput
import glob

for line in fileinput.input(glob.glob("*.txt")):
    if fileinput.isfirstline():
        print('-'*20, f'Reading {fileinput.filename()}...', '-'*20)
    print(str(fileinput.lineno()) + ': ' + line.upper(), end="")

运行效果如下

$ python demo.py
-------------------- Reading b.txt... --------------------
1: HELLO
2: PYTHON
-------------------- Reading a.txt... --------------------
3: HELLO
4: WORLD

4. 读取的同时备份文件

fileinput.input 有一个 backup 参数,你可以指定备份的后缀名,比如 .bak

import fileinput

with 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.py
a.txt 第1行: hello
a.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.bak

5. 标准输出重定向替换

fileinput.input 有一个 inplace 参数,表示是否将标准输出的结果写回文件,默认不取代

请看如下一段测试代码

import fileinput

with fileinput.input(files=("a.txt",), inplace=True) 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.txt
hello
world

$ python demo.py
[INFO] task is started...
[INFO] task is closed...

$ cat a.txt 
a.txt 第1行: hello
a.txt 第2行: world

利用这个机制,可以很容易的实现文本替换。

import sys
import fileinput

for line in fileinput.input(files=('a.txt', ), inplace=True):
    #将Windows/DOS格式下的文本文件转为Linux的文件
    if line[-2:] == "\r\n":  
        line = line + "\n"
    sys.stdout.write(line)

附:如何实现 DOS 和 UNIX 格式互换以供程序测试,使用 vim 输入如下指令即可

DOS转UNIX::setfileformat=unix
UNIX转DOS::setfileformat=dos

6. 不得不介绍的方法

如果只是想要 fileinput 当做是替代 open 读取文件的工具,那么以上的内容足以满足你的要求。

  • fileinput.filenam()

返回当前被读取的文件名。在第一行被读取之前,返回 None。

  • fileinput.fileno()

返回以整数表示的当前文件“文件描述符”。当未打开文件时(处在第一行和文件之间),返回 -1。

  • fileinput.lineno()

返回已被读取的累计行号。在第一行被读取之前,返回 0。在最后一个文件的最后一行被读取之后,返回该行的行号。

  • fileinput.filelineno()

返回当前文件中的行号。在第一行被读取之前,返回 0。在最后一个文件的最后一行被读取之后,返回此文件中该行的行号。

但若要想基于 fileinput 来做一些更加复杂的逻辑,也许你会需要用到如下这几个方法

  • fileinput.isfirstline()

如果刚读取的行是其所在文件的第一行则返回 True,否则返回 False。

  • fileinput.isstdin()

如果最后读取的行来自 sys.stdin 则返回 True,否则返回 False。

  • fileinput.nextfile()

关闭当前文件以使下次迭代将从下一个文件(如果存在)读取第一行;不是从该文件读取的行将不会被计入累计行数。直到下一个文件的第一行被读取之后文件名才会改变。在第一行被读取之前,此函数将不会生效;它不能被用来跳过第一个文件。在最后一个文件的最后一行被读取之后,此函数将不再生效。

  • fileinput.close()

关闭序列。

7. 进阶一点的玩法

在 fileinput.input() 中有一个 openhook 的参数,它支持用户传入自定义的对象读取方法。

若你没有传入任何的勾子,fileinput 默认使用的是 open 函数。

fileinput  为我们内置了两种勾子供你使用

  • fileinput.hook_compressed(*filename*, *mode*)

使用 gzip 和 bz2 模块透明地打开 gzip 和 bzip2 压缩的文件(通过扩展名 '.gz' 和 '.bz2' 来识别)。如果文件扩展名不是 '.gz' 或 '.bz2',文件会以正常方式打开(即使用 open() 并且不带任何解压操作)。使用示例: fi = fileinput.FileInput(openhook=fileinput.hook_compressed)

  • fileinput.hook_encoded(*encoding*, *errors=None*)

返回一个通过 open() 打开每个文件的钩子,使用给定的 encoding 和 errors 来读取文件。使用示例: fi = fileinput.FileInput(openhook=fileinput.hook_encoded("utf-8", "surrogateescape"))

如果你自己的场景比较特殊,以上的三种勾子都不能满足你的要求,你也可以自定义。

这边我举个例子来抛砖引玉下

假如我想要使用 fileinput 来读取网络上的文件,可以这样定义勾子。

  • 先使用 requests 下载文件到本地
  • 再使用 open 去读取它
def online_open(url, mode):
    import requests
    r = 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

直接将这个函数传给 openhook 即可

import fileinput

file_url = 'https://www.csdn.net/robots.txt'
with fileinput.input(files=(file_url,), openhook=online_open) as file:
    for line in file:
        print(line, end="")

运行后按预期一样将 CSDN 的 robots 的文件打印了出来

User-agent: * 
Disallow: /scripts 
Disallow: /public 
Disallow: /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.xml
Sitemap: https://www.csdn.net/article/sitemap.txt 

8. 列举一些实用案例

案例一:读取一个文件所有行

import fileinput
for line in fileinput.input('data.txt'):
  print(line, end="")

案例二:读取多个文件所有行

import fileinput
import glob

for line in fileinput.input(glob.glob("*.txt")):
    if fileinput.isfirstline():
        print('-'*20, f'Reading {fileinput.filename()}...', '-'*20)
    print(str(fileinput.lineno()) + ': ' + line.upper(), end="")

案例三:利用fileinput将CRLF文件转为LF

import sys
import fileinput

for line in fileinput.input(files=('a.txt', ), inplace=True):
    #将Windows/DOS格式下的文本文件转为Linux的文件
    if line[-2:] == "\r\n":  
        line = line + "\n"
    sys.stdout.write(line)

案例四:配合 re 做日志分析:取所有含日期的行

#--样本文件--:error.log
aaa
1970-01-01 13:45:30  Error: **** Due to System Disk spacke not enough...
bbb
1970-01-02 10:20:30  Error: **** Due to System Out of Memory...
ccc

#---测试脚本---
import re
import fileinput
import sys

pattern = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'

for line in fileinput.input('error.log',backup='.bak',inplace=1):
    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...

案例五:利用fileinput实现类似于grep的功能

import sys
import re
import fileinput

pattern= 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 re
addressBook1.py 10  import re
addressBook2.py 18  import re
test.py         238 import re

9. 写在最后

fileinput 是对 open 函数的再次封装,在仅需读取数据的场景中, fileinput 显然比 open 做得更专业、更人性,当然在其他有写操作的复杂场景中,fileinput 就无能为力啦,本身从 fileinput 的命名上就知道这个模块只专注于输入(读)而不是输出(写)。

以上就是python 使用fileinput读取文件的详细内容,更多关于python 用fileinput读取文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python使用os模块和fileinput模块来操作文件目录

    os模块 在python编程中,我们会经常使用到文件和目录,这些操作python提供一个os模块,里面有很多操作文件和目录的函数. 下面介绍os的常用功能 1.获取当前路径 >>> os.getcwd() '/root/python' 2.获取目录中的内容 >>> os.listdir(os.getcwd()) ['deco.py', '6.py', 'inputfile.py', 'uniFile.py', 'oddnogen.py', 'ospathex.py',

  • Python fileinput模块使用介绍

    fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行.它的工作方式和readlines很类似,不同点在于它不是将全部的行读到列表中而是创建了一个xreadlines对象. 下面是fileinput模块中的常用函数: input() #返回能够用于for循环遍历的对象 filename() #返回当前文件的名称 lineno() #返回当前已经读取的行的数量(或者序号) filelineno() #返回当前读取的行的行号 isfirstli

  • Python fileinput模块使用实例

    fileinput模块可以对一个或多个文件中的内容进行迭代.遍历等操作. 该模块的input()函数有点类似文件readlines()方法,区别在于: 前者是一个迭代对象,即每次只生成一行,需要用for循环迭代. 后者是一次性读取所有行.在碰到大文件的读取时,前者无疑效率更高效. 用fileinput对文件进行循环遍历,格式化输出,查找.替换等操作,非常方便. [典型用法] 复制代码 代码如下: import fileinput for line in fileinput.input():   

  • python 使用sys.stdin和fileinput读入标准输入的方法

    1.使用sys.stdin 读取标准输入 [root@c6-ansible-20 script]# cat demo02.py #! /usr/bin/env python from __future__ import print_function import sys for line in sys.stdin: print(line,end="") 使用方法: cat /etc/passwd|python demo02.py python demo02.py </etc/pa

  • Python fileinput模块如何逐行读取多个文件

    Python 提供了 fileinput 模块,通过该模块中的 input() 函数,我们能同时打开指定的多个文件,还可以逐个读取这些文件中的内容. fileinput 模块中 input() 该函数的语法格式如下: fileinput.input(files="filename1, filename2, ...", inplace=False, backup='', bufsize=0, mode='r', openhook=None) 此函数会返回一个 FileInput 对象,它

  • Python中的fileinput模块的简单实用示例

    这几天有这样一个需求,要将用户登陆系统的信息统计出来,做成一个报表.当用户登陆成功的时候,服务器会往日志文件里写一条像下面这种格式的记录:"日期时间@用户名@IP",这样的日志文件第天生成一个.所以,我们只要编历这些日志文件,将所有的登陆信息提取出来,并重新组织数据格式就可以了.用python写一个分析工具非常简单,你会说,用glob获取所有的日志文件,然后对每个日志文件都open(logfile),再一行一行的读取:或者用os.walk,也很简单.其实,标准库提供了另一个辅助模块,我

  • python文件处理fileinput使用方法详解

    这篇文章主要介绍了python文件处理fileinput使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.介绍 fileinput模块可以对一个或多个文件中的内容进行迭代.遍历等操作,我们常用的open函数是对一个文件进行读写操作. fileinput模块的input()函数比open函数更高效和好用,体现在: input()函数生成一个迭代器,保证了在遇到大文件的读取时不会占用太大的内存. 用fileinput对文件进行循环遍历

  • python使用fileinput模块实现逐行读取文件的方法

    本文实例讲述了python使用fileinput模块实现逐行读取文件的方法.分享给大家供大家参考.具体实现方法如下: #-------------------------------- # Name: read_lines.py # Author: Kevin Harris # Last Modified: 02/13/04 # Description: This Python script demonstrates # how to use fileinput to read # each l

  • python 使用fileinput读取文件

    fileinput 是 Python 的内置模块,但我相信,不少人对它都是陌生的.今天我把 fileinput 的所有的用法.功能进行详细的讲解,并列举了一些非常实用的案例,对于理解和使用它可以说完全没有问题. 1. 从标准输入中读取 当你的 Python 脚本没有传入任何参数时,fileinput 默认会以 stdin 作为输入源 # demo.py import fileinput for line in fileinput.input():     print(line)  效果如下,不管

  • Python按行读取文件的简单实现方法

    1:readline() file = open("sample.txt") while 1: line = file.readline() if not line: break pass # do something file.close() 一行一行得从文件读数据,显然比较慢: 不过很省内存: 测试读10M的sample.txt文件,每秒大约读32000行: 2:fileinput import fileinput for line in fileinput.input("

  • Python按行读取文件的实现方法【小文件和大文件读取】

    本文实例讲述了Python按行读取文件的实现方法.分享给大家供大家参考,具体如下: 小文件: #coding=utf-8 #author: walker #date: 2013-12-30 #function: 按行读取小文件 all_lines = [] try: file = open('txt.txt', 'r') all_lines = file.readlines() except IOError as err: print('File error: ' + str(err)) fin

  • Python使用defaultdict读取文件各列的方法

    本文实例讲述了Python使用defaultdict读取文件各列的方法.分享给大家供大家参考,具体如下: #!/usr/bin/python """USAGE: python *.py align_SNP_site out_file""" import sys #import time from collections import Counter #t0=time.clock() info=open(sys.argv[1]) fast=sys.

  • python按行读取文件,去掉每行的换行符\n的实例

    如下所示: for line in file.readlines(): line=line.strip('\n') 以上这篇python按行读取文件,去掉每行的换行符\n的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: Python处理文本换行符实例代码 Python按行读取文件的简单实现方法 python去掉行尾的换行符方法 Python实现读取文件最后n行的方法 python去除空格和换行符的实现方法(推荐)

  • Python实现的读取文件内容并写入其他文件操作示例

    本文实例讲述了Python实现的读取文件内容并写入其他文件操作.分享给大家供大家参考,具体如下: 文件目录结构,如图: read_file.py是工作文件,file_test.py是读取文件源,write_test.py是写入目标文件. 文件A:file_test.py #coding=utf-8 for i in range(1, 10): print i 文件B:read_file.py # coding=utf-8 # 打开件A f = open('./file_test.py', 'rb

  • python按行读取文件并找出其中指定字符串

    python按行读取文件并找出其中指定字符串 #coding=utf-8 import os, time, sys, re #reload(sys) #sys.setdefaultencoding("utf8") # 不设置,否则编码方式不对应,无法找出字符串 file = open(path) sum=0 for line in file.readlines(): #line = line.strip("\n") key = "解析渲染" if

  • python多线程分块读取文件

    本文实例为大家分享了python多线程分块读取文件的具体代码,供大家参考,具体内容如下 # _*_coding:utf-8_*_ import time, threading, ConfigParser ''' Reader类,继承threading.Thread @__init__方法初始化 @run方法实现了读文件的操作 ''' class Reader(threading.Thread): def __init__(self, file_name, start_pos, end_pos):

  • python顺序的读取文件夹下名称有序的文件方法

    如下所示: import os path="/home/test/" #待读取的文件夹 path_list=os.listdir(path) path_list.sort() #对读取的路径进行排序 for filename in path_list: print(os.path.join(path,filename)) 以上这篇python顺序的读取文件夹下名称有序的文件方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • python分批定量读取文件内容,输出到不同文件中的方法

    一.文件内容的分发 应用场景:分批读取共有358086行内容的txt文件,每取1000条输出到一个文件当中 # coding=utf-8 # 分批读取共有358086行内容的txt文件,每取1000条输出到一个文件当中 txt_path = "E:/torrenthandle.txt" base_path="E:/torrent_distribution/" def distribution( ): f = open(txt_path,"r")

随机推荐