42

I have a string that can be a hex number prefixed with "0x" or a decimal number without a special prefix except for possibly a minus sign. "0x123" is in base 16 and "-298" is in base 10.

How do I convert this to an int or long in Python?

I don't want to use eval() since it's unsafe and overkill.

9
  • Why is eval unsafe? Are evil people going to sneak code into those numbers? Who has access to those strings? Are they untrustworthy? Commented Mar 2, 2009 at 22:12
  • 10
    eval is unsafe because it allows arbitrary code to be executed. If you are getting the string from a trusted source, it's still unsafe, it just so happens that you're relying on this trusted source to not take advantage of that. If you were always in control of the string, why was it a string? Commented Mar 2, 2009 at 22:17
  • 2
    No, python code is not safe, and this exact comment applies to importing arbitrary modules etc.. The assumption is that the python code is always written by you, and you trust you. If you're eval-ing a string written by you, why is it an eval at all? Thus my last statement in my reply. Commented Mar 2, 2009 at 22:23
  • 1
    This conversation between S.Lott and Devin Jeapierre is what I see as a problem with the reputation system on SO. Commented Oct 2, 2010 at 19:07
  • 1
    @AaronHall I think the duplicate target is not correct. Although the top answer there happens to mention the int(..., 0) solution, that's not what the OP asks for (for example with string "10" this should return 10, the other question should return 16) -- in fact I'd say that the int(x,0) method is wrong for the other question (for the reason above) Commented Aug 31, 2018 at 0:37

5 Answers 5

85
int("0x123", 0)

(why doesn't int("0x123") do that?)

Sign up to request clarification or add additional context in comments.

4 Comments

It's just the way int is implemented in Python - it assumes decimal unless you explicitly tell it to guess by passing 0 as the radix.
Good, so leading zeros do not default it to oct. int("010") returns 10.
But Python does not represent octal numbers with a leading zero, they should have 0o as the prefix (e.g. 0o10). Still, the most common use-case is to convert from decimal numbers, and that is the default behavior.
It would be better to pass 16 as the radix.
41

Parse base 16 to an integer:

>>> int('0x123', 16)
291

Convert integer to a base 16 string:

>>> hex(291)
'0x123'

Comments

5

Something like this might be what you're looking for.

def convert( aString ):
    if aString.startswith("0x") or aString.startswith("0X"):
        return int(aString,16)
    elif aString.startswith("0"):
        return int(aString,8)
    else:
        return int(aString)

2 Comments

Why not use if aString.upper().startswith('0X'): That way you wouldn't need the or? of course lower() with '0x' also works.
@a2j: There's no great reason. What you can do, however, is use timeit to figure out what the tradeoffs are.
0

If you are doing a lot of go between with different number systems, the bitstring library make a lot of binary/Hex operations easier. It also supports string interpretation:

http://pythonhosted.org/bitstring/

Comments

-4

This is a simpler version which works like a charm. Returns string since hex() returns the same type:

def itoh(int): return hex(int)[2:]

2 Comments

The OP wants to convert a string to an int. Your code goes the other way.
Cunfusing to say the least as you used a python keyword as a name of the parameter

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.