python - পাইথন মধ্যে বড় ফাইল MD5 হ্যাশ পান




hashlib (10)

Django জন্য গৃহীত উত্তর বাস্তবায়ন:

import hashlib
from django.db import models


class MyModel(models.Model):
    file = models.FileField()  # any field based on django.core.files.File

    def get_hash(self):
        hash = hashlib.md5()
        for chunk in self.file.chunks(chunk_size=8192):
            hash.update(chunk)
        return hash.hexdigest()

আমি hashlib ব্যবহার করেছি (যা পাইথন 2.6 / 3.0 এ md5 প্রতিস্থাপন করে) এবং যদি আমি একটি ফাইল hashlib.md5() এবং its content hashlib.md5() ফাংশনে hashlib.md5() তবে এটি ভাল কাজ করে।

সমস্যাটি তাদের বড় আকারের RAM ফাইলের আকার ছাড়িয়ে যেতে পারে।

কিভাবে মেমরিতে পুরো ফাইলটি লোড না করে MD5 হ্যাশ ফাইলটি পেতে হয়?


ফাইলটি 128-বাইট অংশে টুকরো টুকরো করুন এবং update() ব্যবহার করে তাদের MD5 এ ফিড করুন।

এই MD5 আছে 128-বাইট ডাইজেস্ট ব্লক যে উপকার লাগে। মূলত, MD5 digest() ফাইলটি যখন, এটি ঠিক কি করছে।

আপনি যদি প্রতিটি পুনরাবৃত্তির স্মৃতি মুক্ত করেন (অর্থাত পুরো ফাইলটি মেমরিতে পড়েন না) নিশ্চিত করুন, এটি 128 মেগাবাইটের বেশি মেমরি গ্রহণ করবে না।

উদাহরণস্বরূপ অনুচ্ছেদটি পড়ার একটি উদাহরণ হল:

f = open(fileName)
while not endOfFile:
    f.read(128)

import hashlib,re
opened = open('/home/parrot/pass.txt','r')
opened = open.readlines()
for i in opened:
    strip1 = i.strip('\n')
    hash_object = hashlib.md5(strip1.encode())
    hash2 = hash_object.hexdigest()
    print hash2

এই থ্রেডে একাধিক মন্তব্য / উত্তর ব্যবহার করে, এখানে আমার সমাধান:

import hashlib
def md5_for_file(path, block_size=256*128, hr=False):
    '''
    Block size directly depends on the block size of your filesystem
    to avoid performances issues
    Here I have blocks of 4096 octets (Default NTFS)
    '''
    md5 = hashlib.md5()
    with open(path,'rb') as f: 
        for chunk in iter(lambda: f.read(block_size), b''): 
             md5.update(chunk)
    if hr:
        return md5.hexdigest()
    return md5.digest()
  • এটি "পাইথনিক"
  • এটি একটি ফাংশন
  • এটা নিরপেক্ষ মান এড়ানো: সবসময় স্পষ্ট বেশী পছন্দ।
  • এটা (খুব গুরুত্বপূর্ণ) পারফরমেন্স অপ্টিমাইজেশান অনুমতি দেয়

এবং পরিশেষে,

- এটি একটি সম্প্রদায় দ্বারা নির্মিত হয়েছে, আপনার পরামর্শ / ধারনাগুলির জন্য সবাইকে ধন্যবাদ।


জেনেরিক হ্যাশিং ফাংশন সম্পর্কে হকিংয়ের মন্তব্য বিবেচনায় বস্টিয়ান সেমিনে কোডের একটি রিমিক্স ...

def hash_for_file(path, algorithm=hashlib.algorithms[0], block_size=256*128, human_readable=True):
    """
    Block size directly depends on the block size of your filesystem
    to avoid performances issues
    Here I have blocks of 4096 octets (Default NTFS)

    Linux Ext4 block size
    sudo tune2fs -l /dev/sda5 | grep -i 'block size'
    > Block size:               4096

    Input:
        path: a path
        algorithm: an algorithm in hashlib.algorithms
                   ATM: ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
        block_size: a multiple of 128 corresponding to the block size of your filesystem
        human_readable: switch between digest() or hexdigest() output, default hexdigest()
    Output:
        hash
    """
    if algorithm not in hashlib.algorithms:
        raise NameError('The algorithm "{algorithm}" you specified is '
                        'not a member of "hashlib.algorithms"'.format(algorithm=algorithm))

    hash_algo = hashlib.new(algorithm)  # According to hashlib documentation using new()
                                        # will be slower then calling using named
                                        # constructors, ex.: hashlib.md5()
    with open(path, 'rb') as f:
        for chunk in iter(lambda: f.read(block_size), b''):
             hash_algo.update(chunk)
    if human_readable:
        file_hash = hash_algo.hexdigest()
    else:
        file_hash = hash_algo.digest()
    return file_hash

যদি আপনি আরো পাইথনিক (কোনও 'সত্যের সময়') সম্পর্কে ফাইলটি পড়ার উপায়টি এই কোডটি পরীক্ষা করে দেখুন:

import hashlib

def checksum_md5(filename):
    md5 = hashlib.md5()
    with open(filename,'rb') as f: 
        for chunk in iter(lambda: f.read(8192), b''): 
            md5.update(chunk)
    return md5.digest()

উল্লেখ্য যে ইটার () func এওএফ এ স্থগিত হওয়ার জন্য ফেরত ইটারারটারের জন্য একটি খালি বাইট স্ট্রিং প্রয়োজন, কারণ পড়ার () কেবল '' (কেবলমাত্র নয় '') প্রদান করে।


ফাইলটি উপযুক্ত আকারের অংশে পড়তে হবে:

def md5_for_file(f, block_size=2**20):
    md5 = hashlib.md5()
    while True:
        data = f.read(block_size)
        if not data:
            break
        md5.update(data)
    return md5.digest()

দ্রষ্টব্য: নিশ্চিত করুন যে আপনি আপনার ফাইলটিকে 'আরবি' দিয়ে খোলা অবস্থায় খুলুন - অন্যথায় আপনি ভুল ফলাফল পাবেন।

তাই এক পদ্ধতিতে পুরোটা করতে - এরকম কিছু ব্যবহার করুন:

def generate_file_md5(rootdir, filename, blocksize=2**20):
    m = hashlib.md5()
    with open( os.path.join(rootdir, filename) , "rb" ) as f:
        while True:
            buf = f.read(blocksize)
            if not buf:
                break
            m.update( buf )
    return m.hexdigest()

উপরে আপডেট Frerich Raabe দ্বারা প্রদত্ত মন্তব্যগুলির উপর ভিত্তি করে ছিল - এবং আমি এটি পরীক্ষা করে দেখেছি এবং এটি আমার পাইথন 2.7.2 উইন্ডোজ ইনস্টলেশনে সঠিক বলে মনে হয়েছে।

আমি 'জ্যাকসাম' টুল ব্যবহার করে ফলাফলগুলি ক্রস-চেক করেছি।

jacksum -a md5 <filename>

http://www.jonelo.de/java/jacksum/


একটি পাইথন 2/3 পোর্টেবল সমাধান

চেকসাম (MD5, sha1, ইত্যাদি) গণনা করতে, আপনাকে ফাইলটি বাইনারি মোডে খুলতে হবে, কারণ আপনি বাইট মানগুলি সমষ্টিভুক্ত করবেন:

Py27 / py3 পোর্টেবল হতে, আপনাকে io প্যাকেজগুলি ব্যবহার করতে হবে, যেমন:

import hashlib
import io


def md5sum(src):
    md5 = hashlib.md5()
    with io.open(src, mode="rb") as fd:
        content = fd.read()
        md5.update(content)
    return md5

আপনার ফাইলগুলি বড় হলে মেমরিতে সম্পূর্ণ ফাইল সামগ্রী সংরক্ষণ করা এড়াতে আপনি ফাইলগুলি ভাগ করে দেখতে পারেন:

def md5sum(src, length=io.DEFAULT_BUFFER_SIZE):
    md5 = hashlib.md5()
    with io.open(src, mode="rb") as fd:
        for chunk in iter(lambda: fd.read(length), b''):
            md5.update(chunk)
    return md5

এখানে কৌশলটি iter() ফাংশনটি একটি সেটিনেল (খালি স্ট্রিং) ব্যবহার করে।

এই ক্ষেত্রে নির্মিত ইটারারেটর প্রতিটি কলটির তার next() পদ্ধতিতে কোনও আর্গুমেন্ট ছাড়াই [ল্যাম্বা ফাংশন] কল করবে; যদি ফেরত মানটি সেন্টিনেল সমান হয় তবে StopIteration উত্থাপিত হবে, অন্যথায় মানটি ফেরত দেওয়া হবে।

আপনার ফাইলগুলি সত্যিই বড় হলে, আপনাকে অগ্রগতির তথ্য প্রদর্শন করতেও হতে পারে। আপনি কলব্যাক ফাংশন কল করে এটি করতে পারেন যা গণনাকৃত বাইটগুলির প্রিন্ট বা লগ করে:

def md5sum(src, callback, length=io.DEFAULT_BUFFER_SIZE):
    calculated = 0
    md5 = hashlib.md5()
    with io.open(src, mode="rb") as fd:
        for chunk in iter(lambda: fd.read(length), b''):
            md5.update(chunk)
            calculated += len(chunk)
            callback(calculated)
    return md5

আপনি সম্পূর্ণ কন্টেন্ট পড়া ছাড়া md5 এটি পেতে পারেন না। কিন্তু আপনি ব্লক দ্বারা ব্লক ফাইল বিষয়বস্তু পড়তে update ফাংশন ব্যবহার করতে পারেন।
m.update (ক); m.update (b) m.update (a + b) এর সমতুল্য


name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
    new_list.append(item[0])
print(new_list)
try:
    location= new_list.index(name)
except:
    location=-1
print (location)

স্ট্রিং তালিকাতে না থাকলে এটি অ্যাকাউন্টের জন্য, যদি তালিকায় না থাকে তবে অবস্থান = -1





python md5 hashlib