Yeniden kullanılabilir kütüphane dosya boyutu insan tarafından okunabilir sürümü almak için?


238

Web'de, insan tarafından okunabilir boyutu bayt boyutundan döndürmek için bir işlev verecek çeşitli snippet'ler vardır:

>>> human_readable(2048)
'2 kilobytes'
>>>

Ama bunu sağlayan bir Python kütüphanesi var mı?


2
Bunun "kütüphane gerektirecek çok küçük bir görev" başlığı altında olduğunu düşünüyorum. Hurry.filesize kaynağına bakarsanız, bir düzine kod satırı ile sadece tek bir işlev vardır. Ve bu bile sıkıştırılabilir.
Ben Blank

8
Bir kitaplık kullanmanın avantajı, genellikle test edilmesidir (bir düzenlemenin bir hata içeriyor olması durumunda çalıştırılabilecek testleri içerir). Testleri eklerseniz, artık 'düzine kod satırı' :-) değil
Sridhar Ratnakumar

Python topluluğunda tekerleği yeniden icat etme miktarı çılgın ve saçma. Sadece ls -h /path/to/file.ext işi yapar. Bunu söyledikten sonra, kabul edilen cevap iyi bir iş çıkarıyor. Kudo.
Edward Aung

Yanıtlar:


522

Basit bir uygulama ile yukarıdaki "kütüphane gerektirecek çok küçük bir görev" sorununu ele almak:

def sizeof_fmt(num, suffix='B'):
    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
        if abs(num) < 1024.0:
            return "%3.1f%s%s" % (num, unit, suffix)
        num /= 1024.0
    return "%.1f%s%s" % (num, 'Yi', suffix)

Destekler:

  • şu anda bilinen tüm ikili önekler
  • negatif ve pozitif sayılar
  • 1000 Yobibitten büyük sayılar
  • keyfi birimler (belki Gibibits'te saymak istersiniz!)

Misal:

>>> sizeof_fmt(168963795964)
'157.4GiB'

ile Fred Cirera


4
Sayı ve birim arasında boşluk olmalıdır. Html veya lateks çıktısı yapıyorsanız, bu boşluk olmamalıdır.
josch

3
sadece bir düşünce, ancak B(yani bayt dışındaki birimler için ) herhangi bir (?) sonek için faktörün hayır 1000.0yerine olmasını ister misiniz 1024.0?
Aralık'ta Anentropik

5
Ondalık bileşenin hassasiyetini artırmak istiyorsanız, 14. ve 6. satırlarda istediğiniz hassasiyeti değiştirin.
Matthew G

44
Bu "çok küçük bir görev" üzerindeki tüm bu yinelemelerin yakalanması ve testlerle bir kütüphaneye kapsüllenmesi güzel olurdu.
fess.

6
@ MD004 Bunun tam tersi. Ön ekler 1 KB = 1000 B ve 1 KiB = 1024 B olacak şekilde tanımlanır
augurar

116

Aradığınız tüm işlevselliğe sahip bir kütüphane humanize. humanize.naturalsize()aradığınız her şeyi yapıyor gibi görünüyor.


9
OP verileri kullanarak bazı örnekler: humanize.naturalsize(2048) # => '2.0 kB' ,humanize.naturalsize(2048, binary=True) # => '2.0 KiB' humanize.naturalsize(2048, gnu=True) # => '2.0K'
RubenLaguna

32

İşte benim versiyonum. For-loop kullanmaz. Sürekli karmaşıklığa sahiptir, O ( 1 ) ve teoride burada bir for-loop kullanan cevaplardan daha verimlidir.

from math import log
unit_list = zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2])
def sizeof_fmt(num):
    """Human friendly file size"""
    if num > 1:
        exponent = min(int(log(num, 1024)), len(unit_list) - 1)
        quotient = float(num) / 1024**exponent
        unit, num_decimals = unit_list[exponent]
        format_string = '{:.%sf} {}' % (num_decimals)
        return format_string.format(quotient, unit)
    if num == 0:
        return '0 bytes'
    if num == 1:
        return '1 byte'

Neler olup bittiğini daha açık hale getirmek için dize biçimlendirmesinin kodunu atlayabiliriz. İşte işi yapan çizgiler:

exponent = int(log(num, 1024))
quotient = num / 1024**exponent
unit_list[exponent]

2
böyle bir kısa kodu optimize ederken, neden / elif / else kullanmıyorsunuz? Negatif dosya boyutları beklemediğiniz sürece, son kontrol num == 1 gerekli değildir. Aksi takdirde: iyi iş, bu sürümü beğendim.
ted

2
Kodum kesinlikle daha optimize edilebilir. Ancak benim amacım bu görevin sürekli karmaşıklıkla çözülebileceğini göstermekti.
joctee

37
Döngüler için cevaplar da O (1) 'dir, çünkü for döngüler sınırlıdır - hesaplama süreleri girdinin boyutuyla ölçeklendirilmez (sınırsız SI önekimiz yoktur).
Thomas Minor

1
Muhtemelen bu nedenle, biçimlendirme için bir virgül eklemek gerekir 1000olarak gösterecektir 1,000 bytes.
iTayb

3
Python 3 kullanırken zip'in bir yineleyici döndürdüğünü unutmayın, bu yüzden list () ile sarmanız gerekir. unit_list = list(zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
donarb

30

Python 3.6 + 'da aşağıdaki çalışmalar, bence, burada cevabı anlamanın en kolay yolu ve kullanılan ondalık basamak miktarını özelleştirmenizi sağlar.

def human_readable_size(size, decimal_places=3):
    for unit in ['B','KiB','MiB','GiB','TiB']:
        if size < 1024.0:
            break
        size /= 1024.0
    return f"{size:.{decimal_places}f}{unit}"

26

Bu sorunun eski olduğunu bilsem de, yakın zamanda döngülerden kaçınan log2ve sonek listesine bir kaydırma ve bir dizin olarak iki katına çıkan boyut sırasını belirlemek için bir sürüm buldum :

from math import log2

_suffixes = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']

def file_size(size):
    # determine binary order in steps of size 10 
    # (coerce to int, // still returns a float)
    order = int(log2(size) / 10) if size else 0
    # format file size
    # (.4g results in rounded numbers for exact matches and max 3 decimals, 
    # should never resort to exponent values)
    return '{:.4g} {}'.format(size / (1 << (order * 10)), _suffixes[order])

Yine de okunabilirliği için unpythonic olarak düşünülebilir :)


1
Ben log2 şey gibi olsa da, size == 0 işlemek gerekir!
Marti Nito

Ya kaydırmak gerekir sizeveya (1 << (order * 10)içinde float()(piton 2 için) son satırında.
Harvey

Bilginize: bazılarının import mathorada olması gerekebilir .
monsto

@monsto true, added :)
akaIDIOT

Bunun ne kadar kompakt olduğunu seviyorum! Paylaşım için teşekkürler.
John Crawford

17

Her zaman bu adamlardan biri olmalı. Bugün benim. İşte tek satırlık bir çözüm - veya işlev imzasını sayarsanız iki satır.

def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
    """ Returns a human readable string reprentation of bytes"""
    return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:])

>>> human_size(123)
123 bytes
>>> human_size(123456789)
117GB

1
Bilginize, çıktı her zaman aşağı yuvarlanır.
wp-overwatch.com

1
bir listeyi varsayılan argüman olarak kullanmaktan kaçınmak için yöntem içindeki birimlere varsayılan listeyi atamak daha iyi olmaz mıydı? (ve units=Nonebunun yerine kullanarak )
Imanol

3
@ImanolEizaguirre En iyi uygulamalar, önerdiğiniz gibi yapmanın iyi bir fikir olduğunu söyler, bu yüzden yanlışlıkla bir programa hataları tanıtmazsınız. Ancak, ünite listesi hiçbir zaman değiştirilmediği için bu işlev yazıldığı gibi güvenlidir. Değiştirilmiş olsaydı, değişiklikler kalıcı olur ve sonraki işlev çağrıları birimler argümanı için varsayılan argüman olarak listenin manipüle edilmiş bir sürümünü alır.
wp-overwatch.com

Python 3 için, ondalık bir nokta istiyorsanız, bunu kullanın: `` def human_size (fsize, units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']): "<1024 başka human_size (fsize / 1024, birimler [1:]) birimleri` `
Omer

15

Yüklü Django kullanıyorsanız filesizeformat'ı da deneyebilirsiniz :

from django.template.defaultfilters import filesizeformat
filesizeformat(1073741824)

=>

"1.0 GB"

1
Bunun benim için bir dezavantajı, 1024'e bölünmesine rağmen GiB yerine GB kullanması.
1024'e

9

Böyle bir kütüphane acele . Dosya boyutu .

>>> from hurry.filesize import alternative
>>> size(1, system=alternative)
'1 byte'
>>> size(10, system=alternative)
'10 bytes'
>>> size(1024, system=alternative)
'1 KB'

3
Ancak, bu kütüphane çok özelleştirilemez. >>> hurry.filesize ithalat boyutundan >>> boyut (1031053) >>> boyut (3033053) '2M' Açıkça tahmin edilen yerine '2.4M' veya '2423K' göstermesini bekliyorum. 2M'.
Sridhar Ratnakumar

Bağımlılık sistemleri ve benzerleriyle uğraşıyorsanız, kodu acele etmekten çok kolay olduğunu unutmayın. Dosya boyutlandırın ve doğrudan kendi kodunuza koyun. İnsanların burada sağladığı parçacıklar kadar kısa.
mlissner

@SridharRatnakumar, benim matematiksel bakınız, biraz akıllıca aşırı yaklaşım sorunu çözmek için hack . Yaklaşım daha da geliştirilebilir mi?
Acumenus

9

1000 veya kibibit güçlerden birini kullanmak daha standart dostu olacaktır:

def sizeof_fmt(num, use_kibibyte=True):
    base, suffix = [(1000.,'B'),(1024.,'iB')][use_kibibyte]
    for x in ['B'] + map(lambda x: x+suffix, list('kMGTP')):
        if -base < num < base:
            return "%3.1f %s" % (num, x)
        num /= base
    return "%3.1f %s" % (num, x)

PS K (büyük harf) son ekiyle binlerce basan bir kütüphaneye asla güvenmeyin :)


P.S. Never trust a library that prints thousands with the K (uppercase) suffix :)Neden olmasın? Kod mükemmel olabilir ve yazar sadece kasayı kilo olarak düşünmedi. Kuralınıza göre herhangi bir kodu otomatik olarak reddetmek oldukça asinine benziyor ...
Douglas Gaskell

7

Bu, neredeyse her durumda ihtiyacınız olanı yapacak, isteğe bağlı argümanlar ile özelleştirilebilir ve gördüğünüz gibi, hemen hemen kendi kendini belgelendirir:

from math import log
def pretty_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    pow,n=min(int(log(max(n*b**pow,1),b)),len(pre)-1),n*b**pow
    return "%%.%if %%s%%s"%abs(pow%(-pow-1))%(n/b**float(pow),pre[pow],u)

Örnek çıktı:

>>> pretty_size(42)
'42 B'

>>> pretty_size(2015)
'2.0 KiB'

>>> pretty_size(987654321)
'941.9 MiB'

>>> pretty_size(9876543210)
'9.2 GiB'

>>> pretty_size(0.5,pow=1)
'512 B'

>>> pretty_size(0)
'0 B'

Gelişmiş özelleştirmeler:

>>> pretty_size(987654321,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'987.7 megabytes'

>>> pretty_size(9876543210,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'9.9 gigabytes'

Bu kod hem Python 2 hem de Python 3 uyumludur. PEP8 uyumluluğu okuyucu için bir alıştırmadır. Unutmayın, güzel olan çıktı .

Güncelleme:

Binlerce virgül gerekiyorsa, belirgin uzantıyı uygulayın:

def prettier_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    r,f=min(int(log(max(n*b**pow,1),b)),len(pre)-1),'{:,.%if} %s%s'
    return (f%(abs(r%(-r-1)),pre[r],u)).format(n*b**pow/b**float(r))

Örneğin:

>>> pretty_units(987654321098765432109876543210)
'816,968.5 YiB'


6

Hurry.filesize () yöntemine alternatif olarak sağlanan snippet'e dayanarak, burada kullanılan önek temelinde değişen kesinlik sayıları veren bir snippet bulunmaktadır. Bazı parçacıklar kadar kısa değil, ama sonuçları seviyorum.

def human_size(size_bytes):
    """
    format a size in bytes into a 'human' file size, e.g. bytes, KB, MB, GB, TB, PB
    Note that bytes/KB will be reported in whole numbers but MB and above will have greater precision
    e.g. 1 byte, 43 bytes, 443 KB, 4.3 MB, 4.43 GB, etc
    """
    if size_bytes == 1:
        # because I really hate unnecessary plurals
        return "1 byte"

    suffixes_table = [('bytes',0),('KB',0),('MB',1),('GB',2),('TB',2), ('PB',2)]

    num = float(size_bytes)
    for suffix, precision in suffixes_table:
        if num < 1024.0:
            break
        num /= 1024.0

    if precision == 0:
        formatted_size = "%d" % num
    else:
        formatted_size = str(round(num, ndigits=precision))

    return "%s %s" % (formatted_size, suffix)


4

Önceki tüm cevaplardan çizim, işte benim üstlenmem. Dosya boyutunu baytlarda bir tamsayı olarak saklayacak bir nesnedir. Ancak nesneyi yazdırmaya çalıştığınızda, otomatik olarak okunabilir bir sürüm elde edersiniz.

class Filesize(object):
    """
    Container for a size in bytes with a human readable representation
    Use it like this::

        >>> size = Filesize(123123123)
        >>> print size
        '117.4 MB'
    """

    chunk = 1024
    units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
    precisions = [0, 0, 1, 2, 2, 2]

    def __init__(self, size):
        self.size = size

    def __int__(self):
        return self.size

    def __str__(self):
        if self.size == 0: return '0 bytes'
        from math import log
        unit = self.units[min(int(log(self.size, self.chunk)), len(self.units) - 1)]
        return self.format(unit)

    def format(self, unit):
        if unit not in self.units: raise Exception("Not a valid file size unit: %s" % unit)
        if self.size == 1 and unit == 'bytes': return '1 byte'
        exponent = self.units.index(unit)
        quotient = float(self.size) / self.chunk**exponent
        precision = self.precisions[exponent]
        format_string = '{:.%sf} {}' % (precision)
        return format_string.format(quotient, unit)

3

Senderle'ın ondalık sürümünün sabit hassasiyetini seviyorum , bu yüzden yukarıdaki joctee cevabı ile bir çeşit melez (tamsayı olmayan üslerle günlükler alabileceğinizi biliyor muydunuz?):

from math import log
def human_readable_bytes(x):
    # hybrid of https://stackoverflow.com/a/10171475/2595465
    #      with https://stackoverflow.com/a/5414105/2595465
    if x == 0: return '0'
    magnitude = int(log(abs(x),10.24))
    if magnitude > 16:
        format_str = '%iP'
        denominator_mag = 15
    else:
        float_fmt = '%2.1f' if magnitude % 3 == 1 else '%1.2f'
        illion = (magnitude + 1) // 3
        format_str = float_fmt + ['', 'K', 'M', 'G', 'T', 'P'][illion]
    return (format_str % (x * 1.0 / (1024 ** illion))).lstrip('0')



2

Basit bir 2 astar hakkında:

def humanizeFileSize(filesize):
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%.3f%s" % (filesize/math.pow(1024,p), ['B','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

Kaputun altında nasıl çalıştığı aşağıda açıklanmıştır:

  1. Günlük 2'yi (dosya boyutu) hesaplar
  2. En yakın birimi elde etmek için 10'a böler. (örneğin, boyut 5000 bayt ise, en yakın birim Kb, dolayısıyla yanıt X KiB olmalıdır)
  3. İade file_size/value_of_closest_unitünitesi ile birlikte.

Ancak dosya boyutu 0 veya negatifse çalışmaz (günlük 0 ve -ve sayıları için tanımsız olduğu için). Onlar için ek kontroller ekleyebilirsiniz:

def humanizeFileSize(filesize):
    filesize = abs(filesize)
    if (filesize==0):
        return "0 Bytes"
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%0.2f %s" % (filesize/math.pow(1024,p), ['Bytes','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

Örnekler:

>>> humanizeFileSize(538244835492574234)
'478.06 PiB'
>>> humanizeFileSize(-924372537)
'881.55 MiB'
>>> humanizeFileSize(0)
'0 Bytes'

NOT - Kb ve KiB arasında bir fark vardır. KB 1000 bayt, KiB ise 1024 bayt anlamına gelir. KB, MB, GB vb KiB, MiB, GiB oysa 1024 tüm katları olan, 1000 katlarıdır burada bu konuda daha fazla


1
def human_readable_data_quantity(quantity, multiple=1024):
    if quantity == 0:
        quantity = +0
    SUFFIXES = ["B"] + [i + {1000: "B", 1024: "iB"}[multiple] for i in "KMGTPEZY"]
    for suffix in SUFFIXES:
        if quantity < multiple or suffix == SUFFIXES[-1]:
            if suffix == SUFFIXES[0]:
                return "%d%s" % (quantity, suffix)
            else:
                return "%.1f%s" % (quantity, suffix)
        else:
            quantity /= multiple

1

Aşağıda bulmak üzere olduğunuz şey, daha önce yayınlanmış olanlar arasında hiçbir şekilde en performanslı veya en kısa çözüm değildir. Bunun yerine, diğer cevapların çoğunun kaçırdığı belirli bir konuya odaklanmaktadır .

Yani giriş gibi bir 999_995durum verildiğinde:

Python 3.6.1 ...
...
>>> value = 999_995
>>> base = 1000
>>> math.log(value, base)
1.999999276174054

ki, en yakın tamsayıya kısaltılır ve girdiye geri uygulanır.

>>> order = int(math.log(value, base))
>>> value/base**order
999.995

Bu, çıktı hassasiyetini kontrol etmemiz gerekene kadar tam olarak beklediğimiz gibi görünüyor . İşte işler biraz zorlaşmaya başladığında.

2 haneye ayarlanan hassasiyetle:

>>> round(value/base**order, 2)
1000 # K

yerine 1M.

Buna nasıl karşı koyabiliriz?

Tabii ki, açıkça kontrol edebiliriz:

if round(value/base**order, 2) == base:
    order += 1

Ama daha iyisini yapabilir miyiz? orderSon adımı atmadan önce hangi yoldan kesilmesi gerektiğini öğrenebilir miyiz?

Olabiliriz.

0.5 ondalık yuvarlama kuralı varsayarsak, yukarıdaki ifkoşul şuna dönüşür:

resim açıklamasını buraya girin

sonuçlanan

def abbreviate(value, base=1000, precision=2, suffixes=None):
    if suffixes is None:
        suffixes = ['', 'K', 'M', 'B', 'T']

    if value == 0:
        return f'{0}{suffixes[0]}'

    order_max = len(suffixes) - 1
    order = log(abs(value), base)
    order_corr = order - int(order) >= log(base - 0.5/10**precision, base)
    order = min(int(order) + order_corr, order_max)

    factored = round(value/base**order, precision)

    return f'{factored:,g}{suffixes[order]}'

vererek

>>> abbreviate(999_994)
'999.99K'
>>> abbreviate(999_995)
'1M'
>>> abbreviate(999_995, precision=3)
'999.995K'
>>> abbreviate(2042, base=1024)
'1.99K'
>>> abbreviate(2043, base=1024)
'2K'

0

başvurunun Sridhar Ratnakumaryanıtı, güncellendi:

def formatSize(sizeInBytes, decimalNum=1, isUnitWithI=False, sizeUnitSeperator=""):
  """format size to human readable string"""
  # https://en.wikipedia.org/wiki/Binary_prefix#Specific_units_of_IEC_60027-2_A.2_and_ISO.2FIEC_80000
  # K=kilo, M=mega, G=giga, T=tera, P=peta, E=exa, Z=zetta, Y=yotta
  sizeUnitList = ['','K','M','G','T','P','E','Z']
  largestUnit = 'Y'

  if isUnitWithI:
    sizeUnitListWithI = []
    for curIdx, eachUnit in enumerate(sizeUnitList):
      unitWithI = eachUnit
      if curIdx >= 1:
        unitWithI += 'i'
      sizeUnitListWithI.append(unitWithI)

    # sizeUnitListWithI = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
    sizeUnitList = sizeUnitListWithI

    largestUnit += 'i'

  suffix = "B"
  decimalFormat = "." + str(decimalNum) + "f" # ".1f"
  finalFormat = "%" + decimalFormat + sizeUnitSeperator + "%s%s" # "%.1f%s%s"
  sizeNum = sizeInBytes
  for sizeUnit in sizeUnitList:
      if abs(sizeNum) < 1024.0:
        return finalFormat % (sizeNum, sizeUnit, suffix)
      sizeNum /= 1024.0
  return finalFormat % (sizeNum, largestUnit, suffix)

ve örnek çıktı:

def testKb():
  kbSize = 3746
  kbStr = formatSize(kbSize)
  print("%s -> %s" % (kbSize, kbStr))

def testI():
  iSize = 87533
  iStr = formatSize(iSize, isUnitWithI=True)
  print("%s -> %s" % (iSize, iStr))

def testSeparator():
  seperatorSize = 98654
  seperatorStr = formatSize(seperatorSize, sizeUnitSeperator=" ")
  print("%s -> %s" % (seperatorSize, seperatorStr))

def testBytes():
  bytesSize = 352
  bytesStr = formatSize(bytesSize)
  print("%s -> %s" % (bytesSize, bytesStr))

def testMb():
  mbSize = 76383285
  mbStr = formatSize(mbSize, decimalNum=2)
  print("%s -> %s" % (mbSize, mbStr))

def testTb():
  tbSize = 763832854988542
  tbStr = formatSize(tbSize, decimalNum=2)
  print("%s -> %s" % (tbSize, tbStr))

def testPb():
  pbSize = 763832854988542665
  pbStr = formatSize(pbSize, decimalNum=4)
  print("%s -> %s" % (pbSize, pbStr))


def demoFormatSize():
  testKb()
  testI()
  testSeparator()
  testBytes()
  testMb()
  testTb()
  testPb()

  # 3746 -> 3.7KB
  # 87533 -> 85.5KiB
  # 98654 -> 96.3 KB
  # 352 -> 352.0B
  # 76383285 -> 72.84MB
  # 763832854988542 -> 694.70TB
  # 763832854988542665 -> 678.4199PB

0

Bu çözüm, zihninizin nasıl çalıştığına bağlı olarak size de hitap edebilir:

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
>>> get_size("d:\\media\\bags of fun.avi")
'38 MB'
>>> get_size("d:\\media\\bags of fun.avi","KB")
'38,763 KB'
>>> get_size("d:\\media\\bags of fun.avi","kb")
'310,104 kb'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.