import csv
import re

from libqtile.widget import base

sensors_mapping = {
    'fan_speed': 'fan.speed',
    'perf': 'pstate',
    'temp': 'temperature.gpu',
}


class NvidiaSensors(base.ThreadPoolText):
    """Displays temperature, fan speed and performance level Nvidia GPU."""

    orientations = base.ORIENTATION_HORIZONTAL
    defaults = [
        (
            'format', '{temp}°C',
            'Display string format. Three options available:  '
            '``{temp}`` - temperature, ``{fan_speed}`` and ``{perf}`` - '
            'performance level'
        ),
        ('foreground_alert', 'ff0000', 'Foreground colour alert'),
        (
            'gpu_bus_id', '',
            "GPU's Bus ID, ex: ``01:00.0``. If leave empty will display all "
            "available GPU's"
        ),
        ('update_interval', 2, 'Update interval in seconds.'),
        (
            'threshold',
            70,
            'If the current temperature value is above, '
            'then change to foreground_alert colour'
        ),
    ]

    def __init__(self, **config):
        base.ThreadPoolText.__init__(self, '', **config)
        self.add_defaults(NvidiaSensors.defaults)
        self.foreground_normal = self.foreground

    def _get_sensors_data(self, command):
        return csv.reader(
            self.call_process(
                command, shell=True
            ).strip().replace(' ', '').split('\n')
        )

    def poll(self):
        sensors = [sensor for sensor in re.findall('{(.+?)}', self.format)]
        bus_id = f'-i {self.gpu_bus_id}' if self.gpu_bus_id else ''
        command = 'nvidia-smi {} --query-gpu={} --format=csv,noheader'.format(
            bus_id, ",".join(sensors_mapping[sensor] for sensor in sensors)
        )
        sensors_data = [
            dict(zip(sensors, gpu))
            for gpu in self._get_sensors_data(command)
        ]
        for gpu in sensors_data:
            if gpu.get('temp') and int(gpu['temp']) > self.threshold:
                self.foreground = self.foreground_alert
        return ' - '.join([self.format.format(**gpu) for gpu in sensors_data])

@@ -156,16 +156,120 @@
 u',%0A%7D%0A%0A%0A
+def _all_sensors_names_correct(sensors):%0A    return all(map(lambda x: x in sensors_mapping, sensors))%0A%0A%0A
 class Nv
@@ -1538,12 +1538,28 @@
 def 
-poll
+_parse_format_string
 (sel
@@ -1574,19 +1574,16 @@
     
-sensors = %5B
+return %7B
 sens
@@ -1633,17 +1633,175 @@
 .format)
-%5D
+%7D%0A%0A    def poll(self):%0A        sensors = self._parse_format_string()%0A        if not _all_sensors_names_correct(sensors):%0A            return 'Wrong sensor name'
 %0A       
@@ -2026,16 +2026,33 @@
       )%0A
+        try:%0A    
         
@@ -2064,24 +2064,28 @@
 rs_data = %5B%0A
+    
             
@@ -2112,32 +2112,36 @@
 u))%0A            
+    
 for gpu in self.
@@ -2175,18 +2175,26 @@
         
+ 
-%5D%0A
+   %5D%0A    
         
@@ -2230,16 +2230,20 @@
         
+   
+ 
 if gpu.g
@@ -2292,16 +2292,20 @@
 eshold:%0A
+    
         
@@ -2352,32 +2352,36 @@
 d_alert%0A        
+    
 return ' - '.joi
@@ -2382,16 +2382,33 @@
  '.join(
+%0A                
 %5Bself.fo
@@ -2450,10 +2450,73 @@
 rs_data%5D
-)
+%0A            )%0A        except Exception:%0A            return None
 %0A

Add check for correct sensors names in format string, small refactoring