如何检查.xls和.csv文件是否为空

时间:2017-03-01 16:37:26

标签: python python-2.7 csv xls xlrd

问题1:如何检查整个.xls或.csv文件是否为空。这是我正在使用的代码:

try:
    if os.stat(fullpath).st_size > 0:
       readfile(fullpath)
    else:
       print "empty file"
except OSError:
    print "No file"

空的.xls文件大小超过5.6kb,因此它是否有任何内容并不明显。 如何检查xls或csv文件是否为空?

问题2:我需要检查文件的标题。 如何告诉python只有一行标题的文件是空的?

import xlrd
def readfile(fullpath)
    xls=xlrd.open_workbook(fullpath)  
    for sheet in xls.sheets():
        number_of_rows = sheet.nrows 
        number_of_columns = sheet.ncols
        sheetname = sheet.name
        header = sheet.row_values(0) #Then if it contains only headers, treat it as empty.

这是我的尝试。如何继续使用此代码?

请为这两个问题提供解决方案。提前谢谢。

7 个答案:

答案 0 :(得分:8)

使用.empty方法在pandas中这很简单。这样做

import pandas as pd

df = pd.read_csv(filename) # or pd.read_excel(filename) for xls file
df.empty # will return True if the dataframe is empty or False if not.

对于只有标题的文件,这也将返回True,如

>> df = pd.DataFrame(columns = ['A','B'])
>> df.empty
   True

答案 1 :(得分:3)

  

问题1:我如何检查整个.xls文件是否为空。

def readfile(fullpath)
    xls = xlrd.open_workbook(fullpath)

    is_empty = None

    for sheet in xls.sheets():
        number_of_rows = sheet.nrows

        if number_of_rows == 1:
            header = sheet.row_values(0)  
            # then If it contains only headers I want to treat as empty
            if header:
                is_empty = False
                break

        if number_of_rows > 1:
            is_empty = False
            break

        number_of_columns = sheet.ncols
        sheetname = sheet.name

    if is_empty:
        print('xlsx ist empty')
  

问题2:我如何检查文件的标题。如果文件只有一个标题(我的意思是只有一行)我需要把文件视为空。我怎么能这样做。

import csv
with open('test/empty.csv', 'r') as csvfile:
    csv_dict = [row for row in csv.DictReader(csvfile)]
    if len(csv_dict) == 0:
        print('csv file is empty')

使用Python测试:3.4.2

答案 2 :(得分:1)

我不认为Stackoverflow当时允许2个问题,但让我给你我的Excel部分答案

import xlrd
from pprint import pprint

wb = xlrd.open_workbook("temp.xlsx")

empty_sheets = [sheet for sheet in wb.sheets() if sheet.ncols == 0]
non_empty_sheets = [sheet for sheet in wb.sheets() if sheet.ncols > 0]

# printing names of empty sheets
pprint([sheet.name for sheet in empty_sheets])

# writing non empty sheets to database 
pass # write code yourself or ask another question 

关于标题:让我给你一点提示,测试sheet.nrows == 1

答案 3 :(得分:1)

对于你的excel代码,我喜欢有人提出的pandas解决方案,但是如果你在工作但无法安装它,那么我认为你几乎已经采用了你所采用的代码方法。你有一个遍历每张纸的循环。因此,您可以测试每个工作表中的行,然后如果为空则采取适当的操作:

import xlrd

xlFile = "MostlyEmptyBook.xlsx"

def readfile(xlFile):
    xls=xlrd.open_workbook(xlFile)  
    for sheet in xls.sheets():
        number_of_rows = sheet.nrows 
        number_of_columns = sheet.ncols
        sheetname = sheet.name
        header = sheet.row_values(0) #then If it contains only headers I want to treat as empty
        if number_of_rows <= 1:
            # sheet is empty or has just a header
            # do what you want here
            print(xlFile + "is empty.")

注意:我为文件名添加了一个变量,以便在使用时更容易在整个代码中的一个位置进行更改。我还在你的函数声明中添加了:,但它没有。如果您希望测试仅包含标题(我的包含完全空白页),请将<=更改为==

关于相关的csv问题。 csv只是一个文本文件。我们可以合理地确定文件是空的,除了使用类似下面的编码方法的标头。我会在文件样本上尝试这个代码,你可能想调整我的数学逻辑。例如,在if比较中使用+ 1而不是*1.5就可以了。我的想法是使用空格,或者如果错误地包含了一些字符,这将是一个很好的文件大小缓冲+编码逻辑中给出的第二行测试中的字符。

这是基于您想知道在将一些巨型文件加载到计算机之前文件是否为空的假设。如果这个假设是错误的,你可以使用我的测试逻辑,然后保持文件打开,甚至读取更多代码,以确保标题后面没有空行后跟其他内容(在格式错误的输入文件中) :

import os

def convert_bytes(num):
    """
    this function will convert bytes to MB.... GB... etc
    """
    for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
        if num < 1024.0:
            return "%3.1f %s" % (num, x)
        num /= 1024.0


def file_size(file_path):
    """
    this function will return the file size
    """
    if os.path.isfile(file_path):
        file_info = os.stat(file_path)
        return convert_bytes(file_info.st_size)


# testing if a csv file is empty in Python (header has bytes so not zero)

fileToTest = "almostEmptyCSV.csv"

def hasContentBeyondHeader(fileToTest):
    answer = [ True, 0, 0, 0]
    with open(fileToTest) as f:
        lis = [ f.readline(), f.readline() ] 
        answer[1] = len(lis[0])                # length header row
        answer[2] = len(lis[1])                # length of next row
        answer[3] = file_size(fileToTest)      # size of file

        # these conditions should be high confidence file is empty or nearly so
        sizeMult = 1.5   # test w/ your files and adjust as appropriate (but should work)
        charLimit = 5

        if answer[1] * sizeMult > answer[2] and answer[2] == 0:
            answer[0] = False
        elif answer[1] * sizeMult > answer[2] and answer[2] < charLimit:
            # separate condition in case you want to remove it
            # returns False if only a small number of chars (charLimit) on 2nd row
            answer[0] = False
        else:
            answer[0] = True   # added for readability (or delete else and keep default)         

        f.close()
    return answer

hasContentBeyondHeader(fileToTest)  # False if believed to be empty except for header

在测试期间,readline命令从文件中提取此内容:

['year,sex,births\n', '']

示例输出:

[True, 16, 0, '17.0 bytes']

这种方法意味着您可以在它返回的列表的[0]元素中访问测试结果,该结果为True / False。附加元素允许您获取有关程序决策输入的信息,以防您以后想要进行调整。

此代码以自定义文件大小函数开头。如果您正在寻找更短的代码,您可以根据自己的喜好替换它。这将取代前两个微小的功能:

import os    
os.path.getsize(fullpathhere)

答案 4 :(得分:1)

这样的事情:

file = open(path, "r")
file_content = file.read()
file.close()
if file_content == "":
    print("File '{}' is empty".format(path))
else:
    rows = file_content.split("\n", 1)
    if rows[1] == "":
        print("File '{}' contains headers only.".format(path))

其中path是xls或csv文件的路径。

答案 5 :(得分:0)

对于你的问题:

  

问题2:我需要检查文件的标题。我怎么能告诉python只有一行标题的文件是空的?

您只需检查文件中的行。

<img src={require(`${../images/resto.png}`} />

答案 6 :(得分:0)

试试这个可以解决问题。 并非所有空 CSV 文件都是 0 字节。这也适用于那种情况。

import os
from os.path import isfile
import pandas

if isfile(PASSWORD_MANAGER_FILE):
    try:
        pandas.read_csv(PASSWORD_MANAGER_FILE)
    except pandas.errors.EmptyDataError:
        os.remove(PASSWORD_MANAGER_FILE)