Find IPv4 address using Python

Hello,

Does anyone know how to find the Local IPv4 address of the same device, running python code?

I was able to find this on google: socket.gethostbyname(socket.gethostname()). It works on my personal laptop, and returns 192.168.1.130. But returns the following error when ran on a RaspberryPI 3 B+ through the Balena dashboard:

 opencv-test  Traceback (most recent call last):
 opencv-test    File "./main.py", line 51, in <module>
 opencv-test      init()
 opencv-test    File "./main.py", line 39, in init
 opencv-test      ip = socket.gethostbyname(socket.gethostname())
 opencv-test  socket.gaierror: [Errno -5] No address associated with hostname

Does anyone know how to associate the IP address with the hostname, or if there is another way of retrieving the address?

Hi there Nate,

There reason that socket.gethostname doesn’t work on a balena device, is because it will run in a container. The container has a UUID as it’s hostname which won’t resolve to a network adapter.

The simplest way to achieve what you want, is to user the balena supervisor API. Here’s how to do it from the shell:

curl -X GET --header "Content-Type:application/json" "$BALENA_SUPERVISOR_ADDRESS/v1/device?apikey=$BALENA_SUPERVISOR_API_KEY"

This will give you the IP amongst some other bits: https://docs.resin.io/reference/supervisor/supervisor-api/ 36
If your application is running multiple containers, you need to add some labels to your docker-compose file: https://docs.resin.io/learn/develop/multicontainer/#labels

To get this into your python app, you can either make the request from the code (using requests, or similar) or you could run the code in a bash script (if that’s your container entrypoint) and put the result into an environment variable which your python can use.

Hope this helps.
Phil

Thank you, I was able to add the labels to the docker-compose, and when I run this command:

root@855dda1:/usr/src/app# curl -X GET --header "Content-Type:application/json"     "$BALENA_SUPERVISOR_ADDRESS/v1/device?apikey=$BALENA_SUPERVISOR_API_KEY"

It produces this:

{"api_port":48484,"ip_address":"192.168.1.130","os_version":"balenaOS 2.75.0+rev1","mac_address":"B8:27:EB:88:35:2B B8:27:EB:DD:60:7E","supervisor_version":"12.5.10","update_pending":true,"update_failed":false,"update_downloaded":false,"status":"Idle","download_progress":null}root@855dda1:/usr/src/app# 

Which to me indicates that the device IP has made it into the container. I tried print(requests.get("http://127.0.0.1:48484/ip_address").content)and a couple others, but it produces b'Unauthorized'. I am wondering if you would be able to show an example for ether using requests, or the environment variable?

Thank you!

Thanks for getting back. Not sure how the local loopback service can access the /ip_address, but one way you can try this out with request is emulate the balena-supervisor request like:

''' Assuming Python 3 and above '''
requests.get(f"{BALENA_SUPERVISOR_ADDRESS}/v1/device?apikey={BALENA_SUPERVISOR_API_KEY}", headers={"content-type":"application/json"})

This should be able to provide you IP and all the above info you got via terminal.

  • Nitish

Thank you!

I had to change up the code slightly, but I have put it below.

import requests
import os

bsa = os.getenv('BALENA_SUPERVISOR_ADDRESS')
baak = os.getenv('BALENA_SUPERVISOR_API_KEY')
content = requests.get(bsa + "/v1/device?apikey=" + baak, headers={"content-type":"application/json"}).content

-Nate

You might also want to take a look at the ifaddr Python library: