2016-02-17 3 views
4

У меня есть папка с огромными текстовыми файлами. Каждый из них имеет gzipped и весит несколько байт Giga. Я написал фрагмент кода, чтобы разделить содержимое каждого файла gzip: каждый gzip-файл открыт с gzip, затем каждый указанный фрагмент строки считывается и записывается в новый файл gzip.Ошибка Python gzip CRC

Вот код в файле file_compression.py:

import sys, os, file_manipulation as fm 
import gzip 


def splitGzipFile(fileName, dest=None, chunkPerSplit=100, linePerChunk=4, file_field_separator="_", zfill=3 
        , verbose=False, file_permission=None, execute=True): 
    """ 
    Splits a gz file into chunk files. 
    :param fileName: 
    :param chunkPerSplit: 
    :param linePerChunk: 
    :return: 
    """ 
    absPath = os.path.abspath(fileName) 
    baseName = os.path.basename(absPath) 
    dirName = os.path.dirname(absPath) 
    destFolder = dirName if dest is None else dest 


    ## Compute file fields 
    rawBaseName, extensions = baseName.split(os.extsep, 1) 

    if not str(extensions).startswith("."): 
     extensions = "." + extensions 

    file_fields = str(rawBaseName).split(file_field_separator) 
    first_fields = file_fields[:-1] if file_fields.__len__() > 1 else file_fields 
    first_file_part = file_field_separator.join(first_fields) 
    last_file_field = file_fields[-1] if file_fields.__len__() > 1 else "" 
    current_chunk = getCurrentChunkNumber(last_file_field) 
    if current_chunk is None or current_chunk < 0: 
     first_file_part = rawBaseName 

    ## Initialize chunk variables 
    linePerSplit = chunkPerSplit * linePerChunk 
    # chunkCounter = 0 

    chunkCounter = 0 if current_chunk is None else current_chunk-1 

    for chunk in getFileChunks(fileName, linePerSplit): 
     print "writing " + str(str(chunk).__len__()) + " ..." 
     chunkCounter += 1 
     oFile = fm.buildPath(destFolder) + first_file_part + file_field_separator + str(chunkCounter).zfill(zfill) + extensions 

     if execute: 
      writeGzipFile(oFile, chunk, file_permission) 
     if verbose: 
      print "Splitting: created file ", oFile 



def getCurrentChunkNumber(chunk_field): 
    """ 
    Tries to guess an integer from a string. 
    :param chunk_field: 
    :return: an integer, None if failure. 
    """ 
    try: 
     return int(chunk_field) 
    except ValueError: 
     return None 


def getFileChunks(fileName, linePerSplit): 
    with gzip.open(fileName, 'rb') as f: 
     print "gzip open" 
     lineCounter = 0 
     currentChunk = "" 
     for line in f: 
      currentChunk += line 
      lineCounter += 1 
      if lineCounter >= linePerSplit: 
       yield currentChunk 
       currentChunk = "" 
       lineCounter = 0 
     if not currentChunk == '': 
      yield currentChunk 


def writeGzipFile(file_name, content, file_permission=None): 
    import gzip 
    with gzip.open(file_name, 'wb') as f: 
     if not content == '': 
      f.write(content) 

    if file_permission is not None and type(file_permission) == int: 
     os.chmod(file_name, file_permission) 

Эта задача несколько процессов, процесс создается для каждого файла перед тем, как расщепляются. Каждый файл открыт и разделить только один раз, перед тем, как удалить, я убедился в том, что при записи их в списке:

from tools.file_utils import file_compression as fc, file_manipulation as fm 
import multiprocessing 
from multiprocessing import Process, Queue, Manager 

manager = Manager() 
split_seen = manager.list() 

files = [...] # list is full of gzip files. 
processList = [] 
sampleDir = "sample/dir/" 

for file in files: 
    fielPath = sampleDir + str(file) 
    p = Process(target=processFile, args=(filePath, sampleDir, True)) 
    p.start() 
    processList.append(p) 

## Join the processes 
for p in processList: 
    p.join() 

def processFile(filePath, destFolder, verbose=True): 
    global split_seen 
    if filePath in split_seen: 
     print "Duplicate file processed: " + str(filePath) 
     time.sleep(3) 
    print "adding", filePath, split_seen.__len__() 
    split_seen.append(filePath) 
    fc.splitGzipFile(filePath, dest=destFolder, chunkPerSplit=4000000\ 
           , linePerChunk=4 
           , verbose=True 
           , file_permission=0770 
           , zfill=3 
         ) 

    os.remove(filePath) 

До сих пор код всегда работает хорошо. Но сегодня у меня была проблема с GZIP файлы КПР коррупции:

Process Process-3:72: 

Traceback (most recent call last): 

    ... 

    File "/.../tools/file_utils/file_compression.py", line 43, in splitGzipFile 

    for chunk in getFileChunks(fileName, linePerSplit): 

    File "/.../tools/file_utils/file_compression.py", line 70, in getFileChunks 

    for line in f: 

    File "/.../python2.7/lib/python2.7/gzip.py", line 450, in readline 

    c = self.read(readsize) 

    File "/.../python2.7/lib/python2.7/gzip.py", line 256, in read 

    self._read(readsize) 

    File "/.../python2.7/lib/python2.7/gzip.py", line 320, in _read 

    self._read_eof() 

    File "/.../python2.7/lib/python2.7/gzip.py", line 342, in _read_eof 

    hex(self.crc))) 

IOError: CRC check failed 0xddbb6045 != 0x34fd5580L 

Что может быть происхождение по этому вопросу? Я должен снова заявить, что до сих пор работало , папки и файлы всегда имели одинаковую структуру. Разница в этом случае, возможно, заключается в том, что мой скрипт обрабатывает больше файлов gzip, чем обычно, может быть, в два раза больше.

Нельзя ли одновременно обращаться к тем же файлам? Но я серьезно сомневаюсь, я убедился, что это не так, зарегистрировав каждый файл, доступный в моем списке split_seen.

Я бы посоветовал, поскольку у меня больше нет подсказок, где искать.


EDIT 1

Может быть, некоторые открытые файлы были доступны кем-то еще, или в другой программе? Я не могу просить и полагаться на отзывы. Итак, чтобы начать, если бы я должен был поставить multiprocess.Lock, не помешало бы ему изменить какой-либо другой поток, процесс, программу, пользователя и т. Д.? Или это ограничивается только Python? Я не могу найти какой-либо документ.

+0

Вы проверили, был ли файл 'fileName' поврежден, например, с помощью' gunzip'? – xiaohan2012

ответ

1

Я получил ту же ошибку в коде, который работает в течение нескольких месяцев. Оказывается, что источник файла был поврежден для этого конкретного файла. Я вернулся к старому файлу, и он работал нормально, и я использовал более новый файл, и он также отлично работал.

Смежные вопросы