75

I am trying to use str.encode() but I get

>>> "hello".encode(hex)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be string, not builtin_function_or_method

I have tried a bunch of variations and they seem to all work in Python 2.5.2, so what do I need to do to get them to work in Python 3.1?

SilentGhost
  • 287,765
  • 61
  • 300
  • 288
Stuart
  • 1,663
  • 4
  • 21
  • 33

9 Answers9

100

The hex codec has been chucked in 3.x. Use binascii instead:

>>> binascii.hexlify(b'hello')
b'68656c6c6f'
S.Lott
  • 373,146
  • 78
  • 498
  • 766
Ignacio Vazquez-Abrams
  • 740,318
  • 145
  • 1,296
  • 1,325
41

In Python 3.5+, encode the string to bytes and use the hex() method, returning a string.

s = "hello".encode("utf-8").hex()
s
# '68656c6c6f'

Optionally convert the string back to bytes:

b = bytes(s, "utf-8")
b
# b'68656c6c6f'
pylang
  • 34,585
  • 11
  • 114
  • 108
26

You've already got some good answers, but I thought you might be interested in a bit of the background too.

Firstly you're missing the quotes. It should be:

"hello".encode("hex")

Secondly this codec hasn't been ported to Python 3.1. See here. It seems that they haven't yet decided whether or not these codecs should be included in Python 3 or implemented in a different way.

If you look at the diff file attached to that bug you can see the proposed method of implementing it:

import binascii
output = binascii.b2a_hex(input)
Mark Byers
  • 767,688
  • 176
  • 1,542
  • 1,434
23

binascii methodes are easier by the way

>>> import binascii
>>> x=b'test'
>>> x=binascii.hexlify(x)
>>> x
b'74657374'
>>> y=str(x,'ascii')
>>> y
'74657374'
>>> x=binascii.unhexlify(x)
>>> x
b'test'
>>> y=str(x,'ascii')
>>> y
'test'

Hope it helps. :)

iMagur
  • 631
  • 1
  • 5
  • 11
21

The easiest way to do it in Python 3.5 and higher is:

>>> 'halo'.encode().hex()
'68616c6f'

If you manually enter a string into a Python Interpreter using the utf-8 characters, you can do it even faster by typing b before the string:

>>> b'halo'.hex()
'68616c6f'

Equivalent in Python 2.x:

>>> 'halo'.encode('hex')
'68616c6f'
simhumileco
  • 27,137
  • 16
  • 123
  • 105
  • Thank you @ner0 for your important comment! – simhumileco Dec 13 '19 at 08:31
  • 1
    No worries. If v3.4 or below is a requirement, this will do: `from binascii import hexlify str(hexlify(bytes('halo', encoding = 'utf-8')), 'ascii')` – ner0 Dec 13 '19 at 16:15
  • Is this because `.hex()` wasn't added until Python 3.5? A link to the changelog would have been really good in this answer as context :-) – Niels Abildgaard Feb 14 '22 at 11:03
9

In Python 3, all strings are unicode. Usually, if you encode an unicode object to a string, you use .encode('TEXT_ENCODING'), since hex is not a text encoding, you should use codecs.encode() to handle arbitrary codecs. For example:

>>>> "hello".encode('hex')
LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
>>>> import codecs
>>>> codecs.encode(b"hello", 'hex')
b'68656c6c6f'

Again, since "hello" is unicode, you need to indicate it as a byte string before encoding to hexadecimal. This may be more inline with what your original approach of using the encode method.

The differences between binascii.hexlify and codecs.encode are as follow:

  • binascii.hexlify

    Hexadecimal representation of binary data.

    The return value is a bytes object.

    Type: builtin_function_or_method

  • codecs.encode

    encode(obj, [encoding[,errors]]) -> object

    Encodes obj using the codec registered for encoding. encoding defaults to the default encoding. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a ValueError. Other possible values are 'ignore', 'replace' and 'xmlcharrefreplace' as well as any other name registered with codecs.register_error that can handle ValueErrors.

    Type: builtin_function_or_method

Devy
  • 9,115
  • 7
  • 58
  • 56
8

base64.b16encode and base64.b16decode convert bytes to and from hex and work across all Python versions. The codecs approach also works, but is less straightforward in Python 3.

Community
  • 1
  • 1
Gabriel
  • 1,204
  • 12
  • 12
  • This is exactly what I needed! A cross-python version way of hex encoding & decoding. Thanks ^_^ `>>> import base64 >>> key = base64.b16encode(b'0123456789abcdef') >>> base64.b16decode(key) '0123456789abcdef'` – TrinitronX Apr 17 '14 at 06:03
3

Use hexlify - http://epydoc.sourceforge.net/stdlib/binascii-module.html

Ofir
  • 8,049
  • 2
  • 28
  • 44
2

Yet another method:

s = 'hello'

h = ''.join([hex(ord(i)) for i in s]);

# outputs: '0x680x650x6c0x6c0x6f'

This basically splits the string into chars, does the conversion through hex(ord(char)), and joins the chars back together. In case you want the result without the prefix 0x then do:

h = ''.join([str(hex(ord(i)))[2:4] for i in s]);

# outputs: '68656c6c6f'

Tested with Python 3.5.3.

Francis Laclé
  • 374
  • 2
  • 5
  • 21