[Python] How to implement a callback using PyCall?

Discussão em 'Python' iniciado por Stack, Novembro 27, 2025.

  1. Stack

    Stack Membro Participativo

    I would like to access a Python package in Ruby using PyCall.

    The non-blocking function in the Python code below activates a callback.

    Could you help me implement the callback?

    #!/usr/bin/env python
    # start_reading.py
    import time
    import mercury

    def found(tag):
    print(tag.epc.decode()) # Check check
    # print(tags[1].epc.decode())

    reader = mercury.Reader("tmr:///dev/ttyUSB0")

    reader.start_reading(found, on_time=250, off_time=0)
    time.sleep(0.5)
    reader.stop_reading()


    Output start_reading.py:

    b'001853000000000000000012'
    b'34155CACB400000000000125'
    b'34155CACB400000000000125'
    b'34155CACB400000000000125'
    b'001853000000000000000012'
    b'34155CACB400000000000125'
    b'001853000000000000000012'
    b'34155CACB400000000000125'
    b'34155CACB400000000000125'


    This pertains an api for ThingMagic RFID readers, which is a Python wrapper for the original api written in C.

    From the docs:


    reader.start_reading(callback, on_time=250, off_time=0)

    Starts asynchronous reading. It returns immediately and begins a sequence of reads or a continuous read. The results are passed to the callback. The reads are repeated until the reader.stop_reading() method is called

    • callback(TagReadData) will be invoked for every tag detected
    • on_time sets the duration, in milliseconds, for the reader to be actively querying
    • off_time duration, in milliseconds, for the reader to be quiet while querying
    ​

    As follows the parts I got working using a single read function. First the Python code, then Ruby.

    #!/usr/bin/env python
    # read.py
    import mercury
    reader = mercury.Reader("tmr:///dev/ttyUSB0")

    data = reader.read()
    print(data)
    print(f"type: {type(data)}")


    Output read.py:

    [EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
    type: <class 'list'>


    #!/usr/bin/env ruby
    # read.rb
    require 'pycall/import'
    include PyCall::Import
    pyimport :mercury

    reader = mercury.Reader.new("tmr:///dev/ttyUSB0")

    python_data = reader.read()
    puts "python_data: #{python_data}"
    puts "python class: #{python_data.class}"
    puts ""
    ruby_data = python_data.to_ary
    puts "ruby_data: #{ruby_data}"
    puts "ruby class: #{ruby_data.class}"


    Output read.rb:

    python_data: [EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
    python class: <class 'list'>

    ruby_data: [EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
    ruby class: Array


    The above works, as you can see.

    The solution for the callback should be an improvement upon the following code.

    #!/usr/bin/env ruby
    # start_reading.rb
    require 'pycall/import'
    include PyCall::Import
    pyimport :mercury

    def found(tag)
    puts tag.epc
    end

    reader = mercury.Reader.new("tmr:///dev/ttyUSB0")

    reader.start_reading(found, on_time=250, off_time=0) # What should I do here?
    sleep(0.5)
    reader.stop_reading()


    Current output start_reading.rb

    start_reading.rb:7:in `found': wrong number of arguments (given 0, expected 1) (ArgumentError)
    from start_reading.rb:14:in `<main>'

    Continue reading...

Compartilhe esta Página