🚀 Big News:Socket Has Acquired Secure Annex.Learn More →
Socket
Book a DemoSign in
Socket

bitmath

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitmath

Pythonic module for representing and manipulating file sizes with different prefix notations (file size unit conversion)

pipPyPI
Version
2.0.1
Maintainers
1

.. image:: https://readthedocs.org/projects/bitmath/badge/?version=latest :target: http://bitmath.rtfd.org/ :align: right :height: 19 :width: 77

.. image:: https://github.com/timlnx/bitmath/actions/workflows/python.yml/badge.svg :target: https://github.com/timlnx/bitmath/actions/workflows/python.yml

.. image:: https://img.shields.io/github/issues/timlnx/bitmath?style=flat-square :target: https://github.com/timlnx/bitmath/issues :alt: Open issues

.. image:: https://img.shields.io/github/issues-pr/timlnx/bitmath?style=flat-square :target: https://github.com/timlnx/bitmath/pulls :alt: Open pull requests

.. image:: https://img.shields.io/pypi/dm/bitmath?style=flat-square :target: https://pypistats.org/packages/bitmath :alt: PyPI - Package Downloads

.. image:: https://img.shields.io/github/stars/timlnx/bitmath?style=flat-square :target: https://pypistats.org/packages/bitmath :alt: GitHub Project Popularity

.. image:: https://img.shields.io/pypi/l/bitmath?style=flat-square :target: https://opensource.org/licenses/MIT :alt: PyPI - License

.. image:: https://img.shields.io/pypi/implementation/bitmath?style=flat-square :alt: PyPI - Implementation

.. image:: https://img.shields.io/pypi/pyversions/bitmath?style=flat-square :alt: PyPI - Python Version

bitmath

bitmath <http://bitmath.readthedocs.org/en/latest/>_ simplifies many facets of interacting with file sizes in various units. Originally focusing on file size unit conversion, functionality now includes:

  • Converting between SI and NIST prefix units (kB to GiB)
  • Converting between units of the same type (SI to SI, or NIST to NIST)
  • Full NIST unit coverage including ZiB, YiB, Zib, and Yib
  • Automatic human-readable prefix selection (like in hurry.filesize <https://pypi.python.org/pypi/hurry.filesize>_)
  • Basic arithmetic operations (subtracting 42KiB from 50GiB)
  • Capacity math with floor division, modulo, and divmod (GiB(1) // MiB(300), GiB(1) % MiB(300))
  • Rich comparison operations (1024 Bytes == 1KiB)
  • Bitwise operations (<<, >>, &, |, ^)
  • Rounding via math.floor, math.ceil, and round
  • Reading a device's storage capacity (Linux/macOS support only)
  • String parsing, including flexible non-strict parsing of ambiguous input
  • Sorting
  • Summing iterables via built-in sum or bitmath.sum for unit-normalised results
  • f-string and format support via the standard Python formatting protocol
  • argparse <https://docs.python.org/3/library/argparse.html>_ integration as a custom type

In addition to the conversion and math operations, bitmath provides human readable representations of values which are suitable for use in interactive shells as well as larger scripts and applications. The format produced for these representations is customizable via the functionality included in stdlibs string.format <https://docs.python.org/3/library/string.html>_.

In discussion we will refer to the NIST units primarily. I.e., instead of "megabyte" we will refer to "mebibyte". The former is 10^3 = 1,000,000 bytes, whereas the second is 2^20 = 1,048,576 bytes. When you see file sizes or transfer rates in your web browser, most of the time what you're really seeing are the base-2 sizes/rates.

Don't Forget! The source for bitmath is available on GitHub <https://github.com/timlnx/bitmath>_.

And did we mention there are nearly 300 unit tests? Check them out for yourself <https://github.com/timlnx/bitmath/tree/master/tests>_.

Running the tests should be as simple as calling the ci target in the Makefile: make ci. Please file a bug report if you run into issues.

Installation

The easiest way to install bitmath is via dnf (or yum) if you're on a Fedora/RHEL based distribution. bitmath is available in the main Fedora repositories, as well as EPEL Repositories. As of 2023 bitmath is only developed, tested, and supported for currently supported <https://devguide.python.org/versions/>_ Python releases.

.. code-block:: bash

$ sudo dnf install python3-bitmath

PyPI:

You could also install bitmath from PyPI <https://pypi.org/project/bitmath/>_ if you like:

.. code-block:: bash

$ pip install --user bitmath

Source:

To install from source, clone the repository and use pip:

.. code-block:: bash

$ git clone https://github.com/timlnx/bitmath.git $ cd bitmath $ pip install .

To also install the bitmath manpage:

.. code-block:: bash

$ sudo make install

Documentation

The main documentation lives at http://bitmath.readthedocs.org/en/latest/ <http://bitmath.readthedocs.org/en/latest/>_.

Topics include:

  • The bitmath Module

    • Utility Functions
    • Context Managers
    • Module Variables
    • argparse integration
  • The bitmath command-line Tool

  • Classes

    • Initializing
    • Available Classes
    • Class Methods
  • Instances

    • Instance Attributes
    • Instance Methods
    • Instance Properties
    • The Formatting Mini-Language
  • Getting Started

    • Tables of Supported Operations
    • Basic Math
    • Unit Conversion
    • Rich Comparison
    • Sorting
  • Real Life Examples

    • Download Speeds
    • Calculating how many files fit on a device
    • Printing Human-Readable File Sizes in Python
    • Calculating Linux BDP and TCP Window Scaling
  • Contributing to bitmath

  • Appendices

    • Rules for Math
    • On Units
    • Who uses Bitmath
    • Related Projects
  • NEWS

  • Copyright

Examples

Arithmetic

.. code-block:: python

import bitmath log_size = bitmath.kB(137.4) log_zipped_size = bitmath.Byte(987) print("Compression saved %s space" % (log_size - log_zipped_size)) Compression saved 136.413kB space thumb_drive = bitmath.GiB(12) song_size = bitmath.MiB(5) songs_per_drive = thumb_drive / song_size print(songs_per_drive) 2457.6

Capacity Planning

Floor division (//), modulo (%), and divmod() are handy for chunk-and-remainder capacity math. bm1 // bm2 returns an int (how many whole chunks fit); bm1 % bm2 returns a bitmath of the left-hand operand's type (the leftover).

.. code-block:: python

from bitmath import GiB, MiB, TiB disk = GiB(1) chunk = MiB(300)

disk // chunk # how many whole 300 MiB chunks fit? 3 disk % chunk # leftover, typed as the LHS (GiB) GiB(0.12109375) divmod(disk, chunk) # both at once (3, GiB(0.12109375))

Re-express the remainder in a human-readable unit with best_prefix() (or coerce directly with to_MiB(), etc.):

.. code-block:: python

(GiB(1) % MiB(300)).best_prefix() MiB(124.0)

Pair with the bitmath.format context manager for clean reporting across a block of capacity calculations:

.. code-block:: python

import bitmath volume = TiB(1) block = GiB(7) with bitmath.format(fmt_str="{value:.2f} {unit}", bestprefix=True): ... whole, leftover = divmod(volume, block) ... print(f"{whole} whole blocks of {block} fit in {volume}") ... print(f"leftover: {leftover}") 146 whole blocks of 7.00 GiB fit in 1.00 TiB leftover: 2.00 GiB

The identity (a // b) * b + (a % b) == a holds, so divmod round-trips.

Convert Units

File size unit conversion:

.. code-block:: python

from bitmath import * dvd_size = GiB(4.7) print("DVD Size in MiB: %s" % dvd_size.to_MiB()) DVD Size in MiB: 4812.8 MiB

Select a human-readable unit

.. code-block:: python

small_number = kB(100) ugly_number = small_number.to_TiB()

print(ugly_number) 9.09494701773e-08 TiB print(ugly_number.best_prefix()) 97.65625 KiB

Rich Comparison

.. code-block:: python

cd_size = MiB(700) cd_size > dvd_size False cd_size < dvd_size True MiB(1) == KiB(1024) True MiB(1) <= KiB(1024) True

Sorting

.. code-block:: python

sizes = [KiB(7337.0), KiB(1441.0), KiB(2126.0), KiB(2178.0), KiB(2326.0), KiB(4003.0), KiB(48.0), KiB(1770.0), KiB(7892.0), KiB(4190.0)]

print(sorted(sizes)) [KiB(48.0), KiB(1441.0), KiB(1770.0), KiB(2126.0), KiB(2178.0), KiB(2326.0), KiB(4003.0), KiB(4190.0), KiB(7337.0), KiB(7892.0)]

Custom Formatting

  • Use of the custom formatting system
  • All of the available instance properties

Example:

.. code-block:: python

longer_format = """Formatting attributes for %s ...: This instances prefix unit is {unit}, which is a {system} type unit ...: The unit value is {value} ...: This value can be truncated to just 1 digit of precision: {value:.1f} ...: In binary this looks like: {binary} ...: The prefix unit is derived from a base of {base} ...: Which is raised to the power {power} ...: There are {bytes} bytes in this instance ...: The instance is {bits} bits large ...: bytes/bits without trailing decimals: {bytes:.0f}/{bits:.0f}""" % str(ugly_number)

print(ugly_number.format(longer_format)) Formatting attributes for 5.96046447754 MiB This instances prefix unit is MiB, which is a NIST type unit The unit value is 5.96046447754 This value can be truncated to just 1 digit of precision: 6.0 In binary this looks like: 0b10111110101111000010000000 The prefix unit is derived from a base of 2 Which is raised to the power 20 There are 6250000.0 bytes in this instance The instance is 50000000.0 bits large bytes/bits without trailing decimals: 6250000/50000000

Utility Functions

bitmath.getsize()

.. code-block:: python

print(bitmath.getsize('python-bitmath.spec')) 3.7060546875 KiB

bitmath.parse_string()

Parse a string with standard units:

.. code-block:: python

import bitmath a_dvd = bitmath.parse_string("4.7 GiB") print(type(a_dvd)) <class 'bitmath.GiB'> print(a_dvd) 4.7 GiB

bitmath.parse_string_unsafe()

Parse a string with ambiguous units:

.. code-block:: python

import bitmath a_gig = bitmath.parse_string_unsafe("1gb") print(type(a_gig)) <class 'bitmath.GB'> a_gig == bitmath.GB(1) True bitmath.parse_string_unsafe('1gb') == bitmath.parse_string_unsafe('1g') True

bitmath.query_device_capacity()

.. code-block:: python

import bitmath with open('/dev/sda') as fp: ... root_disk = bitmath.query_device_capacity(fp) ... print(root_disk.best_prefix()) ... 238.474937439 GiB

bitmath.listdir()

.. code-block:: python

for i in bitmath.listdir('./tests/', followlinks=True, relpath=True, bestprefix=True): ... print(i) ... ('tests/test_file_size.py', KiB(9.2900390625)) ('tests/test_basic_math.py', KiB(7.1767578125)) ('tests/init.py', KiB(1.974609375)) ('tests/test_bitwise_operations.py', KiB(2.6376953125)) ('tests/test_context_manager.py', KiB(3.7744140625)) ('tests/test_representation.py', KiB(5.2568359375)) ('tests/test_properties.py', KiB(2.03125)) ('tests/test_instantiating.py', KiB(3.4580078125)) ('tests/test_future_math.py', KiB(2.2001953125)) ('tests/test_best_prefix_BASE.py', KiB(2.1044921875)) ('tests/test_rich_comparison.py', KiB(3.9423828125)) ('tests/test_best_prefix_NIST.py', KiB(5.431640625)) ('tests/test_unique_testcase_names.sh', Byte(311.0)) ('tests/.coverage', KiB(3.1708984375)) ('tests/test_best_prefix_SI.py', KiB(5.34375)) ('tests/test_to_built_in_conversion.py', KiB(1.798828125)) ('tests/test_to_Type_conversion.py', KiB(8.0185546875)) ('tests/test_sorting.py', KiB(4.2197265625)) ('tests/listdir_symlinks/10_byte_file_link', Byte(10.0)) ('tests/listdir_symlinks/depth1/depth2/10_byte_file', Byte(10.0)) ('tests/listdir_nosymlinks/depth1/depth2/10_byte_file', Byte(10.0)) ('tests/listdir_nosymlinks/depth1/depth2/1024_byte_file', KiB(1.0)) ('tests/file_sizes/kbytes.test', KiB(1.0)) ('tests/file_sizes/bytes.test', Byte(38.0)) ('tests/listdir/10_byte_file', Byte(10.0))

Formatting

.. code-block:: python

with bitmath.format(fmt_str="[{value:.3f}@{unit}]"): ... for i in bitmath.listdir('./tests/', followlinks=True, relpath=True, bestprefix=True): ... print(i[1]) ... [9.290@KiB] [7.177@KiB] [1.975@KiB] [2.638@KiB] [3.774@KiB] [5.257@KiB] [2.031@KiB] [3.458@KiB] [2.200@KiB] [2.104@KiB] [3.942@KiB] [5.432@KiB] [311.000@Byte] [3.171@KiB] [5.344@KiB] [1.799@KiB] [8.019@KiB] [4.220@KiB] [10.000@Byte] [10.000@Byte] [10.000@Byte] [1.000@KiB] [1.000@KiB] [38.000@Byte] [10.000@Byte]

argparse Integration

A self-contained example showing how to use bitmath as an argparse argument type is available in the Integration Examples <https://bitmath.readthedocs.io/en/latest/integration_examples.html#argparse>_ chapter of the documentation.

.. code-block:: python

import argparse import bitmath

def BitmathType(value): try: return bitmath.parse_string(value) except ValueError: raise argparse.ArgumentTypeError( f"{value!r} is not a recognized bitmath unit string" )

parser = argparse.ArgumentParser() parser.add_argument('--block-size', type=BitmathType, required=True) args = parser.parse_args(['--block-size', '10MiB']) print(args.block_size) # 10.0 MiB

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts