benparse

Bencode parser

benparse is a bencode parser for Python 3. It is capable of reading and creating bencoded files such as torrents

benparse.dump(obj: Any, file: IO[bytes], *, skipinvalid: bool = False, encoding: str = 'utf_8') → None

Convert a Python object into a bencoded byte string, and write the output to a file

Parameters

file

the file to dump the bencoded data to

this should be a file object opened in binary write mode ('wb')

Returns

None

All other arguments are the same as in dumps()

Example

>>> with open('testfile', 'wb') as file:
...     benparse.dump(b'BENCODE_STRING', file)
...
>>> with open('testfile', 'rb') as file:
...     file.read()
...     _ = file.seek(0)
...     benparse.load(file)
...
b'14:BENCODE_STRING'
b'BENCODE_STRING'
benparse.dumps(obj: Any, *, skipinvalid: bool = False, encoding: str = 'utf_8') → bytes

Convert a Python object into a bencoded byte string

Parameters
  • obj

    the Python object to convert

    must be a combination of the following types:

    • mapping (dict)

    • sequence (list, tuple)

    • byte string (bytes, bytearray)

    • str

    • int

    • None (converted into an empty string. top-level only; cannot be within containers)

    Dict keys must be a byte string or string

    Type

    BencodeParamObject if skipinvalid is False (default)

    Any if skipinvalid is True

  • encoding – any strings within obj will be converted into byte strings using this encoding

  • skipinvalid – if True, any objects within obj that are of an invalid type will be skipped and not included in the output instead of raising an exception

Returns

the converted bencoded byte string

Examples

>>> dumps(b'STRING')
b'6:STRING'
>>> dumps(12)
b'i12e'
>>> dumps( {'KEY1': 'VALUE', 'KEY2': 32} )
b'd4:KEY15:VALUE4:KEY2i32ee'
>>> # Using encoding
>>> dumps( ['ITEM1', 'ITEM2', 'ITEM3'], encoding='utf_16' )
b'l12:\xff\xfeI\x00T\x00E\x00M\x001\x0012:\xff\xfeI\x00T\x00E\x00M\x002\x0012:\xff\xfeI\x00T\x00E\x00M\x003\x00e'
>>> # Using skipinvalid
>>> dumps( {'KEY1': 'VALUE', 'KEY2': 46.5} )
TypeError: object '46.5' has an unsupported type: '<class 'float'>'
>>> dumps( {'KEY1': 'VALUE', 'KEY2': 46.5}, skipinvalid=True )
b'd4:KEY15:VALUEe'
benparse.load(file: IO[bytes], *, encoding: Optional[str] = None, strict: bool = True) → Union[bytes, int, Tuple[BencodeReturnObjectNested, ], Dict[bytes, BencodeReturnObjectNested], None, str, Tuple[BencodeReturnObjectDecodedNested, ], Dict[str, BencodeReturnObjectDecodedNested]]

Read a bencoded file, and convert it into a Python object

Parameters

file

the file to read the bencoded data from

this should be a file object opened in binary read mode ('rb')

All other arguments and the return value are the same as in loads()

Example

>>> with open('testfile', 'wb') as file:
...     benparse.dump(b'BENCODE_STRING', file)
...
>>> with open('testfile', 'rb') as file:
...     file.read()
...     _ = file.seek(0)
...     benparse.load(file)
...
b'14:BENCODE_STRING'
b'BENCODE_STRING'
benparse.loads(bencode: bytes, *, encoding: Optional[str] = None, strict: bool = True) → Union[bytes, int, Tuple[BencodeReturnObjectNested, ], Dict[bytes, BencodeReturnObjectNested], None, str, Tuple[BencodeReturnObjectDecodedNested, ], Dict[str, BencodeReturnObjectDecodedNested]]

Convert a bencoded byte string into a Python object

Parameters
  • bencode – the bencode byte string to convert

  • strict

    if True (default), StrictError will be raised if bencode contains any of the following:

    • an integer with leading zeros:

      b'i01e'
      
    • an integer that is negative zero:

      b'i-0e'
      
    • a dict where the keys are not in lexicographical order:

      b'd1:B3:VAL1:A3:VALe'
      

    If False, the error will be ignored, and bencode will be converted anyway

  • encoding

    if provided, all byte strings will be decoded to unicode strings using the given encoding

    By default, all strings will be left as raw byte strings

    Only use this option if you’re sure that bencode only contains strings that can be decoded using encoding. It will raise an exception if unable to

Returns

the converted Python object

Return type

BencodeReturnObject if encoding is None (default)

BencodeReturnObjectDecoded if encoding is given

As long as strict is True and encoding is None (default), you can safely reconvert the object back to bencode using dumps() without any data loss

Examples:

>>> loads(b'6:STRING')
b'STRING'
>>> loads(b'i12e')
12
>>> loads(b'd4:KEY15:VALUE4:KEY2i32ee')
{b'KEY1': b'VALUE', b'KEY2': 32}
# Using strict
>>> loads(b'd1:B3:VAL1:A3:VALe')
benparse.load.StrictError: index 9: dict is out of order. the key b'A' should come before the key b'B'
>>> loads(b'd1:B3:VAL1:A3:VALe', strict=False)
{b'B': b'VAL', b'A': b'VAL'}
# Using encoding
>>> loads(b'6:STRING')
b'STRING'
>>> loads(b'6:STRING', encoding='utf_8')
'STRING'
>>> # UTF-16 encoded strings
>>> loads(b'l12:\xff\xfeI\x00T\x00E\x00M\x001\x0012:\xff\xfeI\x00T\x00E\x00M\x002\x0012:\xff\xfeI\x00T\x00E\x00M\x003\x00e', encoding='utf_16')
('ITEM1', 'ITEM2', 'ITEM3')
class benparse.Delimiter(value)

Bases: enum.IntEnum

Bencode delimiter constants

Contains all delimiters used in bencoded data with their corresponding ASCII code

ZERO through NINE are sequential, meaning that you can use the following method to determine if n is an integer:

Delimiter.ZERO <= n <= Delimiter.NINE
Attributes

Attr

ASCII

DICT

d

LIST

l

INT

i

COLON

:

END

e

MINUS

-

ZERO

0

ONE

1

TWO

2

THREE

3

FOUR

4

FIVE

5

SIX

6

SEVEN

7

EIGHT

8

NINE

9

exception benparse.StrictError

Bases: ValueError

Raised by load() and loads() when an exception that can be ignored by setting strict to False occurs