How to create python bytes object from long hex string?

1,749

Solution 1

result = bytes.fromhex(some_hex_string)

Solution 2

Works in Python 2.7 and higher including python3:

result = bytearray.fromhex('deadbeef')

Note: There seems to be a bug with the bytearray.fromhex() function in Python 2.6. The python.org documentation states that the function accepts a string as an argument, but when applied, the following error is thrown:

>>> bytearray.fromhex('B9 01EF')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: fromhex() argument 1 must be unicode, not str`

Solution 3

You can do this with the hex codec. ie:

>>> s='000000000000484240FA063DE5D0B744ADBED63A81FAEA390000C8428640A43D5005BD44'
>>> s.decode('hex')
'\x00\x00\x00\x00\x00\x00HB@\xfa\x06=\xe5\xd0\xb7D\xad\xbe\xd6:\x81\xfa\xea9\x00\x00\xc8B\x86@\xa4=P\x05\xbdD'

Solution 4

Try the binascii module

from binascii import unhexlify
b = unhexlify(myhexstr)

Solution 5

import binascii

binascii.a2b_hex(hex_string)

Thats the way I did it.

Share:
1,749

Related videos on Youtube

J Seabolt
Author by

J Seabolt

Updated on July 08, 2022

Comments

  • J Seabolt
    J Seabolt almost 2 years

    I am building an application on Rails where a user creates a Test, goes to the show view for that test and fills in a form with an answer to a question. If the answer to the question matches the "correct_answer" (defined in the controller), there will be flash message that the answer was correct and a button to continue to the root_path will appear. If the answer is wrong, the flash says "Wrong answer."

    My problem is that the flash message will say wrong answer even if no answer has been given. I ONLY want that message to appear AFTER the user has submitted the form. I understand why this is happening, I just am unsure about how to fix it. Here is the show view for a test:

    <div class="col-md-8 col-md-push-2">
            <h4>Current Score: <%= @test.score %></h4>
            <br /><br />
    
    
            <div class="form_group">
            <%= form_tag test_path(@test), :method=> 'get' do %>
                <h4>What is my first name?</h4>
                <div class="form-group">
                    <%= text_field_tag :answer, params[:answer], class: 'form-control' %>
                </div>
                <% if !flash[:success] %>
                <div class="form-group">
                    <%= submit_tag "Submit", class: "btn btn-primary" %>
                </div>
                <% end %>
            <% end %>
            </div>
    
            <% if flash[:success] %>
                <%= link_to "Continue", root_path, class: "btn btn-success pull-right" %> 
            <% end %> 
        </div>
    

    Here is the controller for tests, which contains the offending show action:

     class TestsController < ApplicationController
    
    def index 
        @test = Test.new 
        @tests = Test.all
    end 
    
    def show 
        @test = Test.find(params[:id])
        correct_answer = "jack"
        user_answer = params[:answer]
        if user_answer == correct_answer
            flash.now[:success] = "That is correct!"
            new_score = @test.score += 1
            @test.update(score: new_score)
        elsif params[:answer] != correct_answer
            flash.now[:danger] = "Wrong answer" 
        end 
    end 
    
    def create 
        @test = Test.create(test_params)
        if @test.save 
            redirect_to test_path(@test)
            flash[:success] = "Test created"
        else 
            flash[:danger] = "There was a problem"
            render "index" 
        end 
    end 
    
    def destroy 
        @test = Test.find(params[:id])
        if @test.destroy
            flash[:success] = "Your test was removed"
            redirect_to root_path 
        end 
    end 
    
    private 
    
        def test_params
            params.require(:test).permit(:score, :user_id)
        end
    end
    

    Is there a better way to do this? If not, can I somehow stop the flash message from appearing on the initial load? I ONLY want it to appear once the form has been submitted. Thanks in advance.

    • Paul Hoffman
      Paul Hoffman over 10 years
      Note that the answers below may look alike but they return different types of values. s.decode('hex') returns a str, as does unhexlify(s). bytearray.fromhex(s) returns a bytearray. Given the wording of this question, I think the big green checkmark should be on bytearray.fromhex(s), not on s.decode('hex').
    • Ciro Santilli OurBigBook.com
      Ciro Santilli OurBigBook.com almost 7 years
    • B Bulfin
      B Bulfin almost 7 years
      How can it be a duplicate of a question created 2 years later?
    • Pavan
      Pavan almost 7 years
      Does the params[:answer] only available when you submit the form?
    • Pavan
      Pavan almost 7 years
      Also can you update the question with the params that are generated in the server on the initial load?
    • LarsH
      LarsH over 3 years
      @CiroSantilli郝海东冠状病六四事件法轮功 A byte string isn't a byte array. stackoverflow.com/questions/1740696/…
    • Ciro Santilli OurBigBook.com
      Ciro Santilli OurBigBook.com over 3 years
      @LarsH fair enough. @ recursive: date is not the main factor: meta.stackexchange.com/questions/147643/…
  • sath garcia
    sath garcia over 15 years
    Two ways to do it in 2.x, three ways in 3.x. So much for "there's only one way to do it"...
  • Crescent Fresh
    Crescent Fresh over 15 years
    Other two ways are more 'built-in' so I would actually use one of those.
  • Ishbir
    Ishbir over 15 years
    @technomalogical: your comment is irrelevant to the answer; perhaps you should delete it and change it into a post to comp.lang.python .
  • nosklo
    nosklo over 15 years
    @technomalogical: I agree with ΤΖΩΤΖΙΟΥ. Also, you got it wrong. The correct phrase is: There should be one-- and preferably only one --obvious way to do it.
  • Scott Griffiths
    Scott Griffiths almost 13 years
    Note that in Python 3.2 (whether by design or a bug I'm not sure) unhexlify now won't accept a string, but only bytes. Pretty silly really, but it means you'd need to use b = unhexlify(bytes(myhexstr, 'utf-8'))
  • Abbafei
    Abbafei almost 10 years
    codecs.decode('0a0a0a', 'hex_codec') should work for 2.x and 3.x :-)
  • berto
    berto over 8 years
    And one additional step, I wanted a byte string (e.g. Python 3's b'\x04\xea[...]'), which you can get from a bytearray with bytes(bytearray.fromhex('deadbeef'))
  • Martijn Pieters
    Martijn Pieters almost 8 years
    @berto: in that case there is a more direct route in the form of binascii.unhexlify().
  • berto
    berto almost 8 years
    Thanks, @MartijnPieters, I'll give that a shot
  • Bash
    Bash almost 4 years
    This seem like the most direct way to do what the original post is asking. Is there a reason this isn't the accepted answer?
  • Klaws
    Klaws over 3 years
    The fromhex() method (of both bytes and bytearray) will also work when the hex numbers are separated by spaces. Very convenient!
  • Mike Martin
    Mike Martin over 3 years
    This really should be the accepted answer. The current accepted answer does not do what the question asked. It returns a mutable array of bytes, not a bytestring.
  • Mike Martin
    Mike Martin over 3 years
    This answer does not do what the question asked. It returns a mutable array of bytes, not a python bytestring. That's like returning an array of strings rather than a string.
  • LarsH
    LarsH over 3 years
    @MartijnPieters Seems like bytes.fromhex() is also more direct, and a bit less obscure / more parsimonious. docs.python.org/3/library/stdtypes.html#bytes.fromhex
  • Martijn Pieters
    Martijn Pieters over 3 years
    @LarsH: that method is not available in older Python 2 releases. That doesn't matter any more today, but it was an issue in 2016.
  • LarsH
    LarsH over 3 years
    @MartijnPieters I wondered if that was the case, but I didn't look far enough to find out.
  • B Bulfin
    B Bulfin over 2 years
    @MikeMartin I accepted this answer, only 12 years after it was posted.