Python Forum
Code is Working As-Is, Looking for Pointers to Improve - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: General (https://python-forum.io/forum-1.html)
+--- Forum: Code Review (https://python-forum.io/forum-46.html)
+--- Thread: Code is Working As-Is, Looking for Pointers to Improve (/thread-37135.html)



Code is Working As-Is, Looking for Pointers to Improve - ki5nyz - May-04-2022

Raspbian10 (Buster) (Pi-Star image 4.1.6)
Python 2.7.16
My script is working properly, other than I still need to figure out how to set the callsign variable in the bash output in the cmd.

I am looking for pointers and suggestions to make the code look better, and less redundant, possibly using arrays and loops to store the variables to send.
My hangup is the vernacular to google. Any useful input is appreciated.
I am currently going down the "2-dimensional array" rabbit hole, but it may not apply.

Also NOTE: There are limitations on what I can print out to the bash command due to the pocsag pager's screen size, and the RemoteCommand program's message buffer limit, so although I am open to input, there are constraints that I cannot get around.

## pocsagSolar.py - Pull XML data from hamsql
## Parse XML to a POCSAG msg and send via RemoteCommand or DAPNet
#
# John/KI5NYZ 2022
#
# Original script by Josh/KI6NAZ
# Adapted from youtube screenshot https://youtu.be/XnyxwmMPX_g?t=323

import urllib3.request
import xmltodict
import subprocess

callsign = "N0CALL"
rubric1 = "" # Solar Weather
rubric2 = "" # Band Conditions

http = urllib3.PoolManager()

url = 'http://www.hamqsl.com/solarxml.php'
response = http.request('GET',url)

doc = xmltodict.parse(str(response.data))
solarindex = doc['solar']['solardata']['solarflux']
aindex = doc['solar']['solardata']['aindex']
kindex = doc['solar']['solardata']['kindex']
sunspots = doc['solar']['solardata']['sunspots']
snr = doc['solar']['solardata']['signalnoise']
muf = doc['solar']['solardata']['muf']

solarindex = " SFI: {}".format(solarindex)
aindex = " / A: {}".format(aindex)
kindex = " / K: {}".format(kindex)
sunspots = " / Sunspots: {}".format(sunspots)
snr = " / SNR: {}".format(snr)
muf = " / MUF: {}".format(muf)

d0 = doc['solar']['solardata']['calculatedconditions']['band'][0]
d1 = doc['solar']['solardata']['calculatedconditions']['band'][1]
d2 = doc['solar']['solardata']['calculatedconditions']['band'][2]
d3 = doc['solar']['solardata']['calculatedconditions']['band'][3]
n0 = doc['solar']['solardata']['calculatedconditions']['band'][4]
n1 = doc['solar']['solardata']['calculatedconditions']['band'][5]
n2 = doc['solar']['solardata']['calculatedconditions']['band'][6]
n3 = doc['solar']['solardata']['calculatedconditions']['band'][7]
v1 = doc['solar']['solardata']['calculatedvhfconditions']['phenomenon'][2]

for k, v in d0.items():
	d0 = v
for k, v in d1.items():
	d1 = v
for k, v in d2.items():
	d2 = v
for k, v in d3.items():
	d3 = v
for k, v in n0.items():
	n0 = v
for k, v in n1.items():
	n1 = v
for k, v in n2.items():
	n2 = v
for k, v in n3.items():
	n3 = v
for k, v in v1.items():
	v1 = v

d0 = " 80-40:{}".format(d0)
d1 = " 30-20:{}".format(d1)
d2 = " 17-15:{}".format(d2)
d3 = " 12-10:{}".format(d3)
n0 = " 80-40:{}".format(n0)
n1 = " 30-20:{}".format(n1)
n2 = " 17-15:{}".format(n2)
n3 = " 12-10:{}".format(n3)
v1 = " / VHF: {}".format(v1)

#Send Solar Weather via RemoteCommand
cmd = "sudo /usr/local/bin/RemoteCommand 7642 page " + rubric1 + solarindex + kindex + aindex + sunspots + snr + muf + v1
process = subprocess.call(cmd,stdout=subprocess.PIPE, shell=True)

#Send Band Conditions via RemoteCommand
cmd = "sudo /usr/local/bin/RemoteCommand 7642 page " + rubric2 + d0 + d1 + d2 + d3 + n0 + n1 + n2 + n3
process = subprocess.call(cmd,stdout=subprocess.PIPE, shell=True)

#Send Solar Weather via DAPNet
#cmd = "sudo /usr/local/sbin/pistar-dapnetapi N0CALL 'Solar Index:'" + solarindex + kindex + aindex + sunspots + snr + muf + v1
#process = subprocess.call(cmd,stdout=subprocess.PIPE, shell=True)

#Send Band Conditions via DAPNet
#cmd = "sudo /usr/local/sbin/pistar-dapnetapi N0CALL 'Band Conditions:'" + d0 + d1 + d2 + d3 + n0 + n1 + n2 + n3
#process = subprocess.call(cmd,stdout=subprocess.PIPE, shell=True)



RE: Code is Working As-Is, Looking for Pointers to Improve - Gribouillis - May-05-2022

Why use Python 2? First thing to do to make the code look better is to use Python 3. Then avoid numbered variable names such as d0 d1 d2, use lists instead d[0], d[1], d[2].


RE: Code is Working As-Is, Looking for Pointers to Improve - Larz60+ - May-05-2022

do you have an example of what the output should look like if done completely in python?


RE: Code is Working As-Is, Looking for Pointers to Improve - ki5nyz - May-06-2022

(May-05-2022, 09:22 PM)Larz60+ Wrote: do you have an example of what the output should look like if done completely in python?

Rubric 1
SFI: 120 / K: 2 / A: 4 / Sunspots: 85 / SNR: S1-S2 / MUF: 20.54 / VHF: Band Closed
Rubric 2
80-40:Fair 30-20:Good 17-15:Fair 12-10:Fair 30-20:Good 17-15:Fair 12-10:Poor
Both outputs result in easily readable formatting on my pager's tiny screen, that's why the outputs of both rubrics do not match, and also why I had to break it up into two. Rubric 1 word wraps on the screen, so I used "/" to separate the values, and Rubric 2 shows up as a list, with each frequency range and condition on it's own line:
80-40:Fair
30-20:Good
...
...


RE: Code is Working As-Is, Looking for Pointers to Improve - Larz60+ - May-07-2022

Here's a good way to get your data.
I didn't finish it all, but show enough for you to understand how it works.
you will need:
  1. All installs from command line.
  2. requests, install with: pip3 install requests
  3. BeautifulSoup, install with: pip3 install BeautifulSoup4
  4. lxml, install with: pip3 install lxml

There are some printouts (calculatedconditions and calculatedvhfconditions) that are only there to show how this
data is loaded into a list. You can remove the print statements.
Note that I used one of the items from calculatedvhfconditions in the results (VHF) this shows how to fetch from list

You will have to finish display of remaining data. If you have any questions, please ask.
'''
    outputs:

    Rubric 1
        SFI: 120 / K: 2 / A: 4 / Sunspots: 85 / SNR: S1-S2 / MUF: 20.54 / VHF: Band Closed

    Rubric 2
        80-40:Fair 30-20:Good 17-15:Fair 12-10:Fair 30-20:Good 17-15:Fair 12-10:Poor

'''
import requests
# from PrettifyPage import PrettifyPage
from bs4 import BeautifulSoup
from TryPaths import TryPaths
from CreateDict import CreateDict
from xml_to_dict import XMLtoDict


class GetSolarData:
    def __init__(self):
        self.tpath = TryPaths()
        # self.pp = PrettifyPage().prettify
        self.cd = CreateDict()
        self.parser = XMLtoDict()
        self.data = {}

    def dispatch(self):
        data = self.get_data()
        self.process_data(data)

    def get_data(self):
        url = 'http://www.hamqsl.com/solarxml.php'
        response = requests.get(url)
        if response.status_code == 200:
            return BeautifulSoup(response.content, 'lxml')
        else:
            print(f"problem retreving data, status: {response.status_code}")
            return None

    def process_data(seld, data):
        solardata = data.find('solardata')
        calculatedconditions = solardata.calculatedconditions.find_all('band')
        # This print statement just to show list contents -- remove when all working
        print(f"\ncalculatedconditions: {calculatedconditions}")

        calculatedvhfconditions = solardata.calculatedvhfconditions.find_all('phenomenon')
        # This print statement just to show list contents -- remove when all working
        print(f"\ncalculatedvhfconditions: {calculatedvhfconditions}")

        # This is results print --- add similar for remaining data
        print(f"\nSFI: {solardata.solarindex} / K: {solardata.kindex.text} / " \
            f"A: {solardata.aindex.text} / Sunspots: {solardata.sunspots.text} / " \
            f"SNR: {solardata.snr} / MUF: {solardata.muf.text} / VHF: {calculatedvhfconditions[2].text}")


def main():
    gsd = GetSolarData()
    gsd.dispatch()


if __name__ == '__main__':
    main()
results as is:
Output:
calculatedconditions: [<band name="80m-40m" time="day">Fair</band>, <band name="30m-20m" time="day">Good</band>, <band name="17m-15m" time="day">Fair</band>, <band name="12m-10m" time="day">Poor</band>, <band name="80m-40m" time="night">Good</band>, <band name="30m-20m" time="night">Good</band>, <band name="17m-15m" time="night">Fair</band>, <band name="12m-10m" time="night">Poor</band>] calculatedvhfconditions: [<phenomenon location="northern_hemi" name="vhf-aurora">Band Closed</phenomenon>, <phenomenon location="europe" name="E-Skip">High MUF</phenomenon>, <phenomenon location="north_america" name="E-Skip">Band Closed</phenomenon>, <phenomenon location="europe_6m" name="E-Skip">50MHz ES</phenomenon>, <phenomenon location="europe_4m" name="E-Skip">Band Closed</phenomenon>] SFI: None / K: 1 / A: 5 / Sunspots: 64 / SNR: None / MUF: 12.47 / VHF: Band Closed
this is what 'data' looks like (I used python tags to take advantage of scrolling:
<?xml version="1.0" encoding="UTF-8" ?>
<html>
  <body>
    <solar>
      <solardata>
        <source url="http://www.hamqsl.com/solar.html">
          N0NBH
        </source>
        <updated>
          07 May 2022 0934 GMT
        </updated>
        <solarflux>
          119
        </solarflux>
        <aindex>
          5
        </aindex>
        <kindex>
          1
        </kindex>
        <kindexnt>
          No Report
        </kindexnt>
        <xray>
          B6.9
        </xray>
        <sunspots>
          64
        </sunspots>
        <heliumline>
          127.0
        </heliumline>
        <protonflux>
          29
        </protonflux>
        <electonflux>
          1280
        </electonflux>
        <aurora>
          4
        </aurora>
        <normalization>
          1.99
        </normalization>
        <latdegree>
          63.9
        </latdegree>
        <solarwind>
          290.2
        </solarwind>
        <magneticfield>
          -2.2
        </magneticfield>
        <calculatedconditions>
          <band name="80m-40m" time="day">
            Fair
          </band>
          <band name="30m-20m" time="day">
            Good
          </band>
          <band name="17m-15m" time="day">
            Fair
          </band>
          <band name="12m-10m" time="day">
            Poor
          </band>
          <band name="80m-40m" time="night">
            Good
          </band>
          <band name="30m-20m" time="night">
            Good
          </band>
          <band name="17m-15m" time="night">
            Fair
          </band>
          <band name="12m-10m" time="night">
            Poor
          </band>
        </calculatedconditions>
        <calculatedvhfconditions>
          <phenomenon location="northern_hemi" name="vhf-aurora">
            Band Closed
          </phenomenon>
          <phenomenon location="europe" name="E-Skip">
            Band Closed
          </phenomenon>
          <phenomenon location="north_america" name="E-Skip">
            Band Closed
          </phenomenon>
          <phenomenon location="europe_6m" name="E-Skip">
            50MHz ES
          </phenomenon>
          <phenomenon location="europe_4m" name="E-Skip">
            Band Closed
          </phenomenon>
        </calculatedvhfconditions>
        <geomagfield>
          VR QUIET
        </geomagfield>
        <signalnoise>
          S0-S1
        </signalnoise>
        <fof2>
          4.90
        </fof2>
        <muffactor>
          2.04
        </muffactor>
        <muf>
          10.01
        </muf>
      </solardata>
    </solar>
  </body>
</html>
Edit 7:34 EST:
Here's code without extra prints:
'''
    outputs:

    Rubric 1
        SFI: 120 / K: 2 / A: 4 / Sunspots: 85 / SNR: S1-S2 / MUF: 20.54 / VHF: Band Closed

    Rubric 2
        80-40:Fair 30-20:Good 17-15:Fair 12-10:Fair 30-20:Good 17-15:Fair 12-10:Poor

'''
import requests
# from PrettifyPage import PrettifyPage
from bs4 import BeautifulSoup
from TryPaths import TryPaths
from CreateDict import CreateDict
from xml_to_dict import XMLtoDict


class GetSolarData:
    def __init__(self):
        self.tpath = TryPaths()
        # self.pp = PrettifyPage().prettify
        self.cd = CreateDict()
        self.parser = XMLtoDict()
        self.data = {}

    def dispatch(self):
        data = self.get_data()
        self.process_data(data)

    def get_data(self):
        url = 'http://www.hamqsl.com/solarxml.php'
        response = requests.get(url)
        if response.status_code == 200:
            return BeautifulSoup(response.content, 'lxml')
        else:
            print(f"problem retreving data, status: {response.status_code}")
            return None

    def process_data(seld, data):
        solardata = data.find('solardata')
        calculatedconditions = solardata.calculatedconditions.find_all('band')
        calculatedvhfconditions = solardata.calculatedvhfconditions.find_all('phenomenon')

        # This is results print --- add similar for remaining data
        print(f"\nSFI: {solardata.solarindex} / K: {solardata.kindex.text} / " \
            f"A: {solardata.aindex.text} / Sunspots: {solardata.sunspots.text} / " \
            f"SNR: {solardata.snr} / MUF: {solardata.muf.text} / VHF: {calculatedvhfconditions[2].text}")


def main():
    gsd = GetSolarData()
    gsd.dispatch()


if __name__ == '__main__':
    main()
Output:
SFI: None / K: 1 / A: 5 / Sunspots: 64 / SNR: None / MUF: 12.43 / VHF: Band Closed