পাইথনে ফাইলের আকারগুলি রূপান্তর করার আরও ভাল উপায় [বন্ধ]


85

আমি একটি লাইব্রেরি ব্যবহার করছি যা কোনও ফাইল পড়ে এবং এর আকার বাইটে দেয়।

এরপরে এই ফাইলের আকারটি শেষ ব্যবহারকারীর কাছে প্রদর্শিত হবে; এটি বোঝার জন্য তাদের পক্ষে আরও সহজ করার জন্য, আমি স্পষ্টভাবে ফাইলের আকারটি MBভাগ করে এটিকে রূপান্তর করছি 1024.0 * 1024.0। অবশ্যই এটি কাজ করে তবে আমি ভাবছি পাইথনগুলিতে এটি করার আরও ভাল উপায় কি আছে?

আরও ভাল, আমি সম্ভবত একটি stdlib ফাংশন যা আমি চাই টাইপ অনুযায়ী মাপ ম্যানিপুলেট করতে পারেন। যদি আমি নির্দিষ্ট করি তবে MBএটি স্বয়ংক্রিয়ভাবে এটিকে ভাগ করে দেয় 1024.0 * 1024.0। এই লাইনে সামথাইন।


4
সুতরাং একটি লিখুন। আরও নোট করুন যে এখন অনেকগুলি সিস্টেম এমবি ব্যবহার করে 2 ^ 20 এর পরিবর্তে 10 ^ 6 বোঝায়।
টিসি।

6
@AA, @tc: দয়া করে মনে রাখবেন যে এসআই এবং আইইসি আদর্শ kB (Kilo) for 1.000 Byteএবং KiB (Kibi) for 1.024 ByteEn.wikedia.org/wiki/Kibibyte দেখুন ।
ববি

4
@ ববি: কেবি আসলে "কিলোবেল" এর অর্থ 10000 ডিবি সমান। বাইটের জন্য কোনও এসআই ইউনিট নেই। আইআইআরসি, আইইসি কিবি সুপারিশ করে তবে কেবি বা কেবি সংজ্ঞায়িত করে না।
টিসি।

4
@ টিসি। উপসর্গ কিলোটি এসআই দ্বারা 1000 হিসাবে বোঝানো হয় 2
ফোরড

4
আমি বলতে চাইছি উপসর্গগুলি সাধারণত এসআই দ্বারা সংজ্ঞায়িত করা হয়, তবে ডেটা আকারের সংক্ষিপ্ত বিবরণগুলি নয়: পদার্থবিজ্ঞান.নিস্ট . gov / cuu / Units / prefixes.html । এগুলি আইইসি দ্বারা সংজ্ঞায়িত করা হয়েছে: ফিজিক্স.নিস্ট.gov
ফোরড

উত্তর:


103

তাড়াতাড়ি রয়েছে iles ফাইলসাইজ যা বাইটগুলিতে আকার নেবে এবং যদি এটি একটি দুর্দান্ত স্ট্রিং তৈরি করে।

>>> from hurry.filesize import size
>>> size(11000)
'10K'
>>> size(198283722)
'189M'

অথবা আপনি যদি 1K == 1000 চান (যা বেশিরভাগ ব্যবহারকারীরা ধরে নেন):

>>> from hurry.filesize import size, si
>>> size(11000, system=si)
'11K'
>>> size(198283722, system=si)
'198M'

এতে আইসিসির সমর্থনও রয়েছে (তবে এটি দলিল করা হয়নি):

>>> from hurry.filesize import size, iec
>>> size(11000, system=iec)
'10Ki'
>>> size(198283722, system=iec)
'189Mi'

কারণ এটি অসাধারণ মার্তিজান ফ্যাসেন লিখেছেন, কোডটি ছোট, পরিষ্কার এবং এক্সটেনসিবল। আপনার নিজের সিস্টেমে লেখা মরা সহজ।

এখানে একটি:

mysystem = [
    (1024 ** 5, ' Megamanys'),
    (1024 ** 4, ' Lotses'),
    (1024 ** 3, ' Tons'), 
    (1024 ** 2, ' Heaps'), 
    (1024 ** 1, ' Bunches'),
    (1024 ** 0, ' Thingies'),
    ]

এর মতো ব্যবহৃত:

>>> from hurry.filesize import size
>>> size(11000, system=mysystem)
'10 Bunches'
>>> size(198283722, system=mysystem)
'189 Heaps'

4
হুঁ, এখন আমার অন্য পথে যেতে হবে। "1 কেবি" থেকে 1024(কোনও আন্ত)
mlissner

4
শুধুমাত্র অজগর 2
ই তথ্য 128

4
এই প্যাকেজটি দুর্দান্ত হতে পারে তবে বিজোড় লাইসেন্স এবং কোনও অনলাইন উপলভ্য উত্স কোড নেই বলে এটিকে এমন কিছু তৈরি করে আমি এড়াতে খুব খুশি হব। এবং এটি মনে হয় কেবল অজগর 2 সমর্থন করে।
আলমগ কোহেন

4
@ অ্যালমগ কোহেন সোর্সটি অনলাইনে রয়েছে, পিআইপিআই থেকে সরাসরি পাওয়া যায় (কিছু প্যাকেজগুলিতে একটি গিথুব সংগ্রহস্থল নেই, কেবল একটি পিপিআই পৃষ্ঠা আছে) এবং লাইসেন্সটি যে অস্পষ্ট নয়, জেডপিএল হল জোপ পাবলিক লাইসেন্স, যা আমার জ্ঞানের সেরা , বিএসডি-এর মতো। আমি সম্মত হই যে লাইসেন্সিং নিজেই বিজোড়: কোনও মানক 'LICENSE.txt' ফাইল নেই, বা প্রতিটি উত্স ফাইলের শীর্ষে কোনও উপস্থাপনা নেই।
sleblanc

4
অর্ডার মেগাবাইট পাওয়ার জন্য আমি সমীকরণ নিম্নলিখিত হয়নি, bitwise ব্যবহার নাড়াচাড়া অপারেটর: MBFACTOR = float(1 << 20); mb= int(size_in_bytes) / MBFACTOR @LennartRegebro
Alper

151

আমি যা ব্যবহার করি তা এখানে:

import math

def convert_size(size_bytes):
   if size_bytes == 0:
       return "0B"
   size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
   i = int(math.floor(math.log(size_bytes, 1024)))
   p = math.pow(1024, i)
   s = round(size_bytes / p, 2)
   return "%s %s" % (s, size_name[i])

নোট: আকার বাইটে প্রেরণ করা উচিত।


11
আপনি যদি আকারে বাইটে প্রেরণ করছেন তবে আকার_নামের প্রথম উপাদান হিসাবে কেবল "বি" যুক্ত করুন।
tuxGurl

আপনার যদি 0 আকারের বাইট ফাইল থাকে তবে এটি ব্যর্থ হয়। লগ (0, 1024) সংজ্ঞায়িত করা হয় না! এই বিবৃতি i = int (math.floor (math.log (আকার, 1024))) এর আগে আপনার 0 বাইট কেসটি পরীক্ষা করা উচিত।
genclik27

genclik - আপনি ঠিক বলেছেন। আমি সবেমাত্র একটি ছোটখাটো সম্পাদনা জমা দিয়েছি যা এটি ঠিক করবে এবং বাইট থেকে রূপান্তর সক্ষম করবে। ধন্যবাদ, সাপম, আসলটির জন্য
ফার্মার গেডডেন

এইচআই @ ডাব্লুএইচকে কে টুকসগুরাল হিসাবে এটি একটি সহজ সমাধানের কথা উল্লেখ করেছে।
জেমস

4
আসলে আকারের নামগুলি হওয়া দরকার ("বি", "কিবি", "এমআইবি", "জিআইবি", "টিআইবি", "পাইবি", "ইআইবি", "জিবি", "ইআইবি")। আরও তথ্যের জন্য en.wikedia.org/wiki/Mebibyte দেখুন ।
অ্যালেক্স

38

আপনার কোনও আকার বিভাজনের পরিবর্তে বিটওয়াইফ শিফটিং অপারেটর1024 * 1024 ব্যবহার করতে পারেন , অর্থাৎ মেগাবাইট পেতে,<< 1<<201<<30 গিগা বাইটস পেতে পেতে etc.

সরল দৃশ্যে আপনার কাছে যেমন একটি ধ্রুবক MBFACTOR = float(1<<20)থাকতে পারে যা বাইটের সাহায্যে ব্যবহার করা যায়, অর্থাত:megas = size_in_bytes/MBFACTOR

মেগাবাইট সাধারণত আপনার যা প্রয়োজন তা হ'ল, নাহলে এর মতো কিছু ব্যবহার করা যেতে পারে:

# bytes pretty-printing
UNITS_MAPPING = [
    (1<<50, ' PB'),
    (1<<40, ' TB'),
    (1<<30, ' GB'),
    (1<<20, ' MB'),
    (1<<10, ' KB'),
    (1, (' byte', ' bytes')),
]


def pretty_size(bytes, units=UNITS_MAPPING):
    """Get human-readable file sizes.
    simplified version of https://pypi.python.org/pypi/hurry.filesize/
    """
    for factor, suffix in units:
        if bytes >= factor:
            break
    amount = int(bytes / factor)

    if isinstance(suffix, tuple):
        singular, multiple = suffix
        if amount == 1:
            suffix = singular
        else:
            suffix = multiple
    return str(amount) + suffix

print(pretty_size(1))
print(pretty_size(42))
print(pretty_size(4096))
print(pretty_size(238048577))
print(pretty_size(334073741824))
print(pretty_size(96995116277763))
print(pretty_size(3125899904842624))

## [Out] ###########################
1 byte
42 bytes
4 KB
227 MB
311 GB
88 TB
2 PB

10
তাই না >>?
তেজুরিরিমুরি

4
@ জোজুরিরিরি: এটি অবশ্যই একটি বাম শিফট হতে হবে, ডান স্থানান্তরটি কেবল বিটটি ছাড়বে এবং ফলস্বরূপ হবে 0
সিসিপিজ্জা

উজ্জ্বল উত্তর। ধন্যবাদ.
বোরিস্লাভ আইমালিয়েভ

আমি জানি এটি পুরানো, তবে এটি কি সঠিক ব্যবহার হবে? Def রূপান্তর_তো_বিএম (ডেটা_বি): মুদ্রণ (ডেটা_বি / (1 << 20%)
রোস্টবিইফ

24

আকার গণনা করার জন্য এখানে কমপ্যাক্ট ফাংশন

def GetHumanReadable(size,precision=2):
    suffixes=['B','KB','MB','GB','TB']
    suffixIndex = 0
    while size > 1024 and suffixIndex < 4:
        suffixIndex += 1 #increment the index of the suffix
        size = size/1024.0 #apply the division
    return "%.*f%s"%(precision,size,suffixes[suffixIndex])

আরও বিস্তারিত আউটপুট এবং তদ্বিপরীত অপারেশনের জন্য দয়া করে রেফার করুন: http://code.activestate.com/recips/578019-bytes-to-human-human-to-bytes-converter/


15

আপনি যদি চান তা ইতিমধ্যে জানেন তবে একক কোডের কোডের মধ্যে ফাইল আকারগুলি মুদ্রণের জন্য দ্রুত এবং অপেক্ষাকৃত সহজ-সরল পন্থার জন্য নীচে দেখুন। এই ওয়ান- লাইনারগুলি এখানে সিপিপিজার দুর্দান্ত উত্তরটি একত্রিত করেছে যে আমি এখানে পড়া কিছু হ্যান্ডেল ফর্ম্যাটিং ট্রিকস সহ হাজার বিভাজক হিসাবে কমা দিয়ে সংখ্যা কীভাবে মুদ্রণ করব?

বাইটস

print ('{:,.0f}'.format(os.path.getsize(filepath))+" B")

কিলোবিটস

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<7))+" kb")

কিলোবাইটস

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<10))+" KB")

মেগাবাইটস

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<17))+" mb")

মেগাবাইট

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<20))+" MB")

গিগাবিটস

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<27))+" gb")

গিগাবাইট

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<30))+" GB")

টেরাবাইট

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<40))+" TB")

স্পষ্টতই তারা ধরে নিয়েছে যে আপনি মোটামুটিভাবে আপনি যে আকারটি শুরুতে মোকাবেলা করতে যাচ্ছেন তা জানেন, যা আমার ক্ষেত্রে (দক্ষিণ পশ্চিম লন্ডন টিভিতে ভিডিও সম্পাদক) এমবি এবং মাঝে মাঝে ভিডিও ক্লিপের জন্য জিবি।


পাথলিবের ব্যবহার আপডেট করুন হিল্ডির মন্তব্যের জবাবে, কেবল পাইথন স্ট্যান্ডার্ড লাইব্রেরিটি ব্যবহার করে একটি কমপ্যাক্ট ফাংশন (জিনিসগুলিকে মার্জ করার পরিবর্তে 'পারমাণবিক' রাখার জন্য) আমার পরামর্শটি এখানে দেওয়া হয়েছে:

from pathlib import Path    

def get_size(path = Path('.')):
    """ Gets file size, or total directory size """
    if path.is_file():
        size = path.stat().st_size
    elif path.is_dir():
        size = sum(file.stat().st_size for file in path.glob('*.*'))
    return size

def format_size(path, unit="MB"):
    """ Converts integers to common size units used in computing """
    bit_shift = {"B": 0,
            "kb": 7,
            "KB": 10,
            "mb": 17,
            "MB": 20,
            "gb": 27,
            "GB": 30,
            "TB": 40,}
    return "{:,.0f}".format(get_size(path) / float(1 << bit_shift[unit])) + " " + unit

# Tests and test results
>>> format_size("d:\\media\\bags of fun.avi")
'38 MB'
>>> format_size("d:\\media\\bags of fun.avi","KB")
'38,763 KB'
>>> format_size("d:\\media\\bags of fun.avi","kb")
'310,104 kb'

4
এটি করার একটি দুর্দান্ত চালাক উপায়। আমি ভাবছি যদি আপনি এগুলি এমন কোনও ফাংশনে রেখে দিতে পারেন যেখানে আপনি কেবি চান কিনা তা আপনি পাস করেন pass এমবি এর এবং তাই। এমনকি আপনার কাছে একটি ইনপুট কমান্ডও থাকতে পারে যা আপনাকে জিজ্ঞাসা করবে যে কোনটি আপনি চান, যা আপনি যদি এটি অনেক কিছু করেন তবে বেশ সুবিধাজনক হবে।
হিলডি

উপরে দেখুন, হিলডি ... আপনি উপরে উল্লিখিত @ লেনার্ট-রেজেব্রোর মতো অভিধানের লাইকটিও কাস্টমাইজ করতে পারেন ... এটি স্টোরেজ পরিচালনার জন্য যেমন দরকারী হতে পারে যেমন "পার্টিশন", "ক্লাস্টার", "4 টিবি ডিস্ক", "ডিভিডি_আরডাব্লু", " ব্লু-রে ডিস্ক "," 1 জিবি মেমরি স্টিকস "বা যাই হোক না কেন।
পিটার এফ

আমি সবেমাত্র কেবি (কিলোবিট), এমবি (মেগাবিত) এবং জিবি (গিগাবিট) যুক্ত করেছি - ব্যবহারকারীরা প্রায়শই তাদের নেটওয়ার্ক বা ফাইল-স্থানান্তর গতির ক্ষেত্রে বিভ্রান্ত করেন, তাই ভেবেছিলেন এটি কার্যকর হতে পারে।
পিটার এফ

9

এই সমস্যার বিপরীতটির জন্য যে কেউ অনুসন্ধান করছে কেবলমাত্র (যেমন আমি নিশ্চিত হয়েছি) এখানে আমার জন্য কী কাজ করে তা এখানে:

def get_bytes(size, suffix):
    size = int(float(size))
    suffix = suffix.lower()

    if suffix == 'kb' or suffix == 'kib':
        return size << 10
    elif suffix == 'mb' or suffix == 'mib':
        return size << 20
    elif suffix == 'gb' or suffix == 'gib':
        return size << 30

    return False

আপনি দশমিক সংখ্যা হিসাবে দশমিক সংখ্যার ক্ষেত্রে পরিচালনা করছেন না। এটা শুধু পরিবর্তন সমাধানের জন্য << 10করতে * 1024, << 20করতে * 1024**2এবং << 30করতে * 1024**3
E235

3

এটা এখানে:

def convert_bytes(size):
   for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
       if size < 1024.0:
           return "%3.1f %s" % (size, x)
       size /= 1024.0

   return size

2

এখানে আমার দুটি সেন্ট, যা উপরে এবং নীচে ingালাইয়ের অনুমতি দেয় এবং কাস্টমাইজযোগ্য নির্ভুলতা যুক্ত করে:

def convertFloatToDecimal(f=0.0, precision=2):
    '''
    Convert a float to string of decimal.
    precision: by default 2.
    If no arg provided, return "0.00".
    '''
    return ("%." + str(precision) + "f") % f

def formatFileSize(size, sizeIn, sizeOut, precision=0):
    '''
    Convert file size to a string representing its value in B, KB, MB and GB.
    The convention is based on sizeIn as original unit and sizeOut
    as final unit. 
    '''
    assert sizeIn.upper() in {"B", "KB", "MB", "GB"}, "sizeIn type error"
    assert sizeOut.upper() in {"B", "KB", "MB", "GB"}, "sizeOut type error"
    if sizeIn == "B":
        if sizeOut == "KB":
            return convertFloatToDecimal((size/1024.0), precision)
        elif sizeOut == "MB":
            return convertFloatToDecimal((size/1024.0**2), precision)
        elif sizeOut == "GB":
            return convertFloatToDecimal((size/1024.0**3), precision)
    elif sizeIn == "KB":
        if sizeOut == "B":
            return convertFloatToDecimal((size*1024.0), precision)
        elif sizeOut == "MB":
            return convertFloatToDecimal((size/1024.0), precision)
        elif sizeOut == "GB":
            return convertFloatToDecimal((size/1024.0**2), precision)
    elif sizeIn == "MB":
        if sizeOut == "B":
            return convertFloatToDecimal((size*1024.0**2), precision)
        elif sizeOut == "KB":
            return convertFloatToDecimal((size*1024.0), precision)
        elif sizeOut == "GB":
            return convertFloatToDecimal((size/1024.0), precision)
    elif sizeIn == "GB":
        if sizeOut == "B":
            return convertFloatToDecimal((size*1024.0**3), precision)
        elif sizeOut == "KB":
            return convertFloatToDecimal((size*1024.0**2), precision)
        elif sizeOut == "MB":
            return convertFloatToDecimal((size*1024.0), precision)

আপনার TBইচ্ছামত যোগ করুন ইত্যাদি।


আমি এটিকে ভোট দেবো কারণ এটি কেবল অজগর স্ট্যান্ডার্ড লাইব্রেরি
দিয়েই

1
UNITS = {1000: ['KB', 'MB', 'GB'],
            1024: ['KiB', 'MiB', 'GiB']}

def approximate_size(size, flag_1024_or_1000=True):
    mult = 1024 if flag_1024_or_1000 else 1000
    for unit in UNITS[mult]:
        size = size / mult
        if size < mult:
            return '{0:.3f} {1}'.format(size, unit)

approximate_size(2123, False)

এটি অনেক সেটিংসে ব্যবহারযোগ্য। খুশি আমি এই মন্তব্য জুড়ে এসেছি। অনেক ধন্যবাদ.
সৌরভ জৈন

0

Ls -lh এর আউটপুটটির সাথে মিল রয়েছে এমন একটি সংস্করণ এখানে ।

def human_size(num: int) -> str:
    base = 1
    for unit in ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']:
        n = num / base
        if n < 9.95 and unit != 'B':
            # Less than 10 then keep 1 decimal place
            value = "{:.1f}{}".format(n, unit)
            return value
        if round(n) < 1000:
            # Less than 4 digits so use this
            value = "{}{}".format(round(n), unit)
            return value
        base *= 1024
    value = "{}{}".format(round(n), unit)
    return value

0

আমি ২ টি উপায় রূপান্তর চেয়েছিলাম এবং আমি পাইথন 3 ফর্ম্যাট () সমর্থনটি সর্বাধিক পাইথনিক হিসাবে ব্যবহার করতে চাই। ডাটাবেস লাইব্রেরি মডিউল চেষ্টা করতে পারেন? https://pypi.org/project/datasize/

$ pip install -qqq datasize
$ python
...
>>> from datasize import DataSize
>>> 'My new {:GB} SSD really only stores {:.2GiB} of data.'.format(DataSize('750GB'),DataSize(DataSize('750GB') * 0.8))
'My new 750GB SSD really only stores 558.79GiB of data.'

-1

আমার বাস্তবায়ন এখানে:

from bisect import bisect

def to_filesize(bytes_num, si=True):
    decade = 1000 if si else 1024
    partitions = tuple(decade ** n for n in range(1, 6))
    suffixes = tuple('BKMGTP')

    i = bisect(partitions, bytes_num)
    s = suffixes[i]

    for n in range(i):
        bytes_num /= decade

    f = '{:.3f}'.format(bytes_num)

    return '{}{}'.format(f.rstrip('0').rstrip('.'), s)

এটি তিন দশমিক ছয় পর্যন্ত মুদ্রণ করবে এবং এটি শূন্য ও পিরিয়ডগুলি পিছনে ফেলে। বুলিয়ান প্যারামিটারsi 10-ভিত্তিক বনাম 2-ভিত্তিক আকারের আকারের টগল করবে।

এটি তার সমমনা এটি পরিষ্কার কনফিগারেশন ফাইলগুলি লিখতে দেয় {'maximum_filesize': from_filesize('10M')। এটি একটি পূর্ণসংখ্যা ফেরত দেয় যা উদ্দেশ্যে করা ফাইলাইজের সংলগ্ন হয়। আমি বিট শিফটিংটি ব্যবহার করছি না কারণ উত্সের মানটি একটি ভাসমান পয়েন্ট সংখ্যা (এটি from_filesize('2.15M')কেবল সূক্ষ্ম গ্রহণ করবে )। এটি একটি পূর্ণসংখ্যার / দশমিক হিসাবে রূপান্তর করা কাজ করবে তবে কোডটিকে আরও জটিল করে তোলে এবং এটি ইতিমধ্যে যেমনটি কাজ করে তেমন কাজ করে।

def from_filesize(spec, si=True):
    decade = 1000 if si else 1024
    suffixes = tuple('BKMGTP')

    num = float(spec[:-1])
    s = spec[-1]
    i = suffixes.index(s)

    for n in range(i):
        num *= decade

    return int(num)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.