added runtimestats

This commit is contained in:
Nico Melone
2023-01-17 23:06:47 -06:00
parent 17b83fa45e
commit bc9e45e18f
5 changed files with 887 additions and 0 deletions

BIN
.DS_Store vendored

Binary file not shown.

291
abbflow/modbusMap.json Normal file
View File

@@ -0,0 +1,291 @@
{
"1": {
"c": "M1-232",
"b": "9600",
"addresses": {
"1": {
"2-2": {
"ah": "",
"bytary": null,
"al": "",
"vn": "Volume Flow",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 1301.77,
"chn": "volume_flow",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502726350.068169,
"a": "4003",
"c": "20.0",
"misc_u": "MCF/Day",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-2",
"mv": "0",
"s": "On",
"r": "0-5000",
"t": "float",
"vm": null
},
"2-3": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Today Volume",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 214.742,
"chn": "today_volume",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502726379.1855018,
"r": "0-1000",
"a": "4005",
"c": "10.0",
"misc_u": "MCF",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-3",
"s": "On",
"mv": "0",
"t": "float",
"vm": null
},
"2-1": {
"ah": "",
"bytary": null,
"al": "",
"vn": "Battery Voltage",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 12.477,
"chn": "battery_voltage",
"r": "0-50",
"dn": "abbflow",
"da": "1",
"lrt": 1502725891.07102,
"a": "4001",
"c": "5",
"misc_u": "V",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-1",
"mv": "0",
"s": "On",
"un": "1",
"t": "float",
"vm": null
},
"2-6": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Last Calc. Period Volume",
"ct": "number",
"le": "32",
"grp": "86400",
"la": 14.691,
"chn": "last_calculation_period_volume",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502682560.730711,
"a": "4011",
"c": "10",
"misc_u": "SCF",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-6",
"mv": "0",
"s": "On",
"r": "0-1000000",
"t": "float",
"vm": null
},
"2-7": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Differential Pressure",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 3.095,
"chn": "differential_pressure",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502725891.811299,
"r": "0-500",
"a": "4013",
"c": "5",
"misc_u": "InH20",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-7",
"s": "On",
"mv": "0",
"t": "float",
"vm": null
},
"2-4": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Yesterday Volume",
"ct": "number",
"le": "32",
"grp": "21600",
"la": 640.448,
"chn": "yesterday_volume",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502517692.3270173,
"a": "4007",
"c": "10.0",
"misc_u": "MCF",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-4",
"mv": "0",
"s": "On",
"r": "0-5000",
"t": "float",
"vm": null
},
"2-5": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Accumulated Volume",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 23666.424,
"chn": "accumulated_volume",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502726134.0120883,
"a": "4009",
"c": "10",
"misc_u": "MCF",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-5",
"mv": "0",
"s": "On",
"r": "0-1000000",
"t": "float",
"vm": null
},
"2-8": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Static Pressure",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 27.048,
"chn": "static_pressure",
"r": "0-250",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502725884.245366,
"a": "4015",
"c": "5",
"misc_u": "PSIA",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-8",
"s": "On",
"mv": "0",
"t": "float",
"vm": null
},
"2-9": {
"ah": "",
"bytary": null,
"al": "0",
"vn": "Temperature",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 85.208,
"chn": "temperature",
"r": "0-300",
"un": "1",
"dn": "abbflow",
"da": "1",
"lrt": 1502724763.458232,
"a": "4017",
"c": "5",
"misc_u": "deg F",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-9",
"s": "On",
"mv": "0",
"t": "float",
"vm": null
},
"2-10": {
"ah": "",
"bytary": null,
"al": "",
"vn": "Charger Voltage",
"ct": "number",
"le": "32",
"grp": "3600",
"la": 13.356,
"chn": "charger_voltage",
"r": "0-50",
"dn": "abbflow",
"da": "1",
"lrt": 1502725893.760519,
"a": "4019",
"c": "5",
"misc_u": "V",
"f": "4",
"mrt": "60",
"m": "none",
"m1ch": "2-10",
"mv": "0",
"s": "On",
"un": "1",
"t": "float",
"vm": null
}
}
},
"f": "Off",
"p": "",
"s": "1"
},
"2": {
"c": "M1-232",
"b": "9600",
"addresses": {},
"f": "Off",
"p": "",
"s": "1"
}
}

View File

@@ -89,6 +89,7 @@ except:
from Tags import tags
CHANNELS = tags
from runtimeStats import RuntimeStats as RTS
class start(threading.Thread, deviceBase):
"""Start class required by Meshify."""
@@ -110,6 +111,8 @@ class start(threading.Thread, deviceBase):
self.public_ip_address_last_checked = 0
self.status = ""
self.alarm = ""
self.rts = RTS()
self.rts.loadDataFromFile()
threading.Thread.start(self)
# this is a required function for all drivers, its goal is to upload some piece of data
@@ -194,6 +197,23 @@ class start(threading.Thread, deviceBase):
self.sendtodbDev(1, "run_status", "Running", 0, 'PiFlow')
else:
self.sendtodbDev(1,"run_status", "Stopped", 0, 'PiFlow')
elif chan.mesh_name == "run_status":
if "Operating" in val and not self.rts.runs[self.rts.todayString]["run_" + str(self.rts.currentRun)]["start"]:
self.rts.startRun()
self.rts.saveDataToFile()
elif "Stopped" in val and self.rts.runs[self.rts.todayString]["run_" + str(self.rts.currentRun)]["start"] and not self.rts.runs[self.rts.todayString]["run_" + str(self.rts.currentRun)]["end"]:
self.rts.endRun()
self.rts.saveDataToFile()
if chan.check(val, self.force_send):
self.sendtodbDev(1, chan.mesh_name, chan.value, 0, 'PiFlow')
self.sendtodbDev(1, "percentRunTime30Days", self.rts.calculateRunPercentMultiDay(), 0,'PiFlow')
elif chan.mesh_name == "frequency":
if val > 0:
self.rts.addHertzDataPoint(val)
self.rts.saveDataToFile()
if chan.check(val, self.force_send):
self.sendtodbDev(1, chan.mesh_name, chan.value, 0, 'PiFlow')
self.sendtodbDev(1, "avgFrequency30Days", self.rts.calculateAverageHertzMultiDay(),0,'PiFlow')
elif chan.mesh_name == "remote_start":
if chan.check(val, self.force_send):
self.sendtodbDev(1, chan.mesh_name, chan.value, 0, 'PiFlow')

157
piflow/runtimeStats.py Normal file
View File

@@ -0,0 +1,157 @@
from datetime import datetime as dt
import time
import json
import math
class RuntimeStats:
def __init__(self):
self.runs = {}
self.currentRun = 0
self.today = ""
self.todayString = ""
def manageTime(self):
if self.today != dt.today():
if self.runs[self.todayString]["run_" + str(self.currentRun)]["start"] and not self.runs[self.todayString]["run_" + str(self.currentRun)]["end"]:
self.runs[self.todayString]["run_" + str(self.currentRun)]["end"] = time.mktime(dt.strptime(self.todayString + " 23:59:59", "%Y-%m-%d %H:%M:%S").timetuple())
self.addDay()
days = list(self.runs.keys())
days.sort()
while (dt.strptime(days[-1],"%Y-%m-%d") - dt.strptime(days[0], "%Y-%m-%d")).days > 30:
self.removeDay(day=days[0])
days = list(self.runs.keys())
days.sort()
def addHertzDataPoint(self, frequency):
if frequency > 0:
self.manageTime()
try:
self.runs[self.todayString]["run_" + str(self.currentRun)]["frequencies"].append(frequency)
except:
self.runs[self.todayString]["run_" + str(self.currentRun)]["frequencies"] = [frequency]
def startRun(self):
self.runs[self.todayString]["run_" + str(self.currentRun)]["start"] = time.time()
def endRun(self):
self.runs[self.todayString]["run_" + str(self.currentRun)]["end"] = time.time()
def addDay(self):
self.today = dt.today()
self.todayString = dt.strftime(self.today, "%Y-%m-%d")
self.currentRun = 1
self.runs[self.todayString] = {}
self.runs[self.todayString]["run_" + str(self.currentRun)] = {"start":0, "end": 0, "frequencies":[]}
def countRunsDay(self, day=None):
if not day:
day = self.todayString
return len(self.runs[day].keys())
def countRunsMultiDay(self, numDays=30):
total_runs = 0
for day in list(self.runs.keys()):
total_runs += self.countRunsDay(day=day)
return total_runs
def calculateAverageHertzDay(self, day=None, returnArray=False):
dayFrequencies = []
if not day:
day = self.todayString
for run in list(self.runs[day].keys()):
try:
dayFrequencies += self.runs[day][run]["frequencies"]
except Exception as e:
print("{} missing frequency data for {}".format(day,run))
if returnArray:
return dayFrequencies
return round(math.fsum(dayFrequencies)/len(dayFrequencies),2)
def calculateAverageHertzMultiDay(self, numDays=30):
self.manageTime()
frequencies = []
for day in list(self.runs.keys()):
try:
frequencies += self.calculateAverageHertzDay(day=day, returnArray=True)
except Exception as e:
print("{} missing frequency data".format(day))
return round(math.fsum(frequencies)/len(frequencies), 2)
def calculateRunTimeDay(self, day=None, convertToHours=True):
total_time = 0
if not day:
day = self.todayString
for run in list(self.runs[day].keys()):
total_time = self.runs[day][run]["end"] - self.runs[day][run]["start"] + total_time
if convertToHours:
return self.convertSecondstoHours(total_time)
return total_time
def calculateRunTimeMultiDay(self, numDays=30, convertToHours=True):
total_time = 0
for day in list(self.runs.keys()):
total_time += self.calculateRunTimeDay(day=day, convertToHours=False)
if convertToHours:
return self.convertSecondstoHours(total_time)
return total_time
def calculateRunPercentDay(self, day=None, precise=False):
if not day:
day = self.todayString
if precise:
return (self.calculateRunTimeDay(day=day)/24) * 100
return round((self.calculateRunTimeDay(day=day)/24) * 100, 2)
def calculateRunPercentMultiDay(self, numDays=30, precise=False):
self.manageTime()
if precise:
return (self.calculateRunTimeMultiDay()/(24*numDays)) * 100
return round((self.calculateRunTimeMultiDay()/(24*numDays)) * 100,2)
def removeDay(self, day=None):
if not day:
raise Exception("Day can not be None")
print("removing day {}".format(day))
del self.runs[day]
def convertSecondstoHours(self, seconds):
return round(seconds / (60*60),2)
def loadDataFromFile(self, filePath="./runtimestats.json"):
try:
with open(filePath, "r") as f:
temp = json.load(f)
self.runs = temp["data"]
self.currentRun = temp["current_run"]
self.today = dt.strptime(temp["current_day"], "%Y-%m-%d")
self.todayString = temp["current_day"]
self.manageTime()
except:
print("Could not find file at {}".format(filePath))
print("creating file")
self.addDay()
try:
with open(filePath, "w") as f:
d = {
"current_run": self.currentRun,
"current_day": self.todayString,
"data": self.runs
}
json.dump(d, f, indent=4)
except Exception as e:
print(e)
def saveDataToFile(self, filePath="./runtimestats.json"):
try:
print("Saving Runs")
with open(filePath, "w") as f:
d = {
"current_run": self.currentRun,
"current_day": self.todayString,
"data": self.runs
}
json.dump(d, f, indent=4)
except Exception as e:
print(e)

419
piflow/runtimestats.ipynb Normal file
View File

@@ -0,0 +1,419 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime as dt\n",
"from datetime import timedelta as td\n",
"from time import sleep\n",
"import json\n",
"import math"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"class RuntimeStats:\n",
" \n",
" def __init__(self):\n",
" self.runs = {}\n",
" self.currentRun = 1\n",
" self.today = dt.today()\n",
" self.todayString = str(self.today.year)+\"-\"+str(self.today.month)+\"-\"+str(self.today.day)\n",
"\n",
" def addHertzDataPoint(self, frequency):\n",
" try:\n",
" self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"].append(frequency)\n",
" except:\n",
" self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"] = [frequency]\n",
"\n",
" def startRun(self):\n",
" self.runs[self.todayString][\"run_\" + str(self.currentRun)] = {\"start\": dt.timestamp(dt.now())}\n",
" \n",
"\n",
" def endRun(self):\n",
" self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"] = dt.timestamp(self.today) \n",
" self.currentRun += 1\n",
"\n",
" def countRunsDay(self, day=None):\n",
" if not day:\n",
" day = self.todayString\n",
" return len(self.runs[day].keys())\n",
"\n",
" def countRunsMultiDay(self, numDays=30):\n",
" total_runs = 0\n",
" for day in list(self.runs.keys()):\n",
" total_runs += self.countRunsDay(day=day)\n",
" return total_runs\n",
"\n",
" def calculateAverageHertzDay(self, day=None, returnArray=False):\n",
" dayFrequencies = []\n",
" if not day:\n",
" day = self.todayString\n",
" for run in list(self.runs[day].keys()):\n",
" try:\n",
" dayFrequencies += self.runs[day][run][\"frequencies\"]\n",
" except Exception as e:\n",
" print(\"{} missing frequency data for {}\".format(day,run))\n",
" if returnArray:\n",
" return dayFrequencies\n",
" return round(math.fsum(dayFrequencies)/len(dayFrequencies),2)\n",
"\n",
" def calculateAverageHertzMultiDay(self, numDays=30):\n",
" frequencies = []\n",
" for day in list(self.runs.keys()):\n",
" try:\n",
" frequencies += self.calculateAverageHertzDay(day=day, returnArray=True)\n",
" except Exception as e:\n",
" print(\"{} missing frequency data\".format(day))\n",
" return round(math.fsum(frequencies)/len(frequencies), 2)\n",
" \n",
" def calculateRunTimeDay(self, day=None, convertToHours=True):\n",
" total_time = 0\n",
" if not day:\n",
" day = self.todayString\n",
" for key in list(self.runs[day].keys()):\n",
" total_time = self.runs[day][key][\"end\"] - self.runs[day][key][\"start\"] + total_time\n",
" if convertToHours:\n",
" return RuntimeStats.convertSecondstoHours(total_time)\n",
" return total_time\n",
"\n",
" def calculateRunTimeMultiDay(self, numDays=30, convertToHours=True):\n",
" total_time = 0\n",
" for day in list(self.runs.keys()):\n",
" total_time += self.calculateRunTimeDay(day=day, convertToHours=False)\n",
" if convertToHours:\n",
" return RuntimeStats.convertSecondstoHours(total_time)\n",
" return total_time\n",
" \n",
" def calculateRunPercentDay(self, day=None, precise=False):\n",
" if not day:\n",
" day = self.todayString\n",
" if precise:\n",
" return (self.calculateRunTimeDay(day=day)/24) * 100\n",
" return round((self.calculateRunTimeDay(day=day)/24) * 100, 2)\n",
" \n",
"\n",
" def calculateRunPercentMultiDay(self, numDays=30, precise=False):\n",
" if precise:\n",
" return (self.calculateRunTimeMultiDay()/(24*numDays)) * 100\n",
" return round((self.calculateRunTimeMultiDay()/(24*numDays)) * 100,2)\n",
"\n",
" def removeDay(self, day=None):\n",
" if not day:\n",
" raise Exception(\"Day can not be None\")\n",
" del self.runs[day]\n",
" \n",
" def convertSecondstoHours(seconds):\n",
" return round(seconds / (60*60),2)\n",
"\n",
" def loadDataFromFile(self, filePath=\"../runtimestats.json\"):\n",
" try:\n",
" with open(filePath, \"r\") as f:\n",
" self.runs = json.load(f)\n",
" except FileExistsError:\n",
" print(\"Could not find file at {}\".format(filePath))\n",
" except FileNotFoundError:\n",
" print(\"Could not find file at {}\".format(filePath))\n",
" print(\"creating file\")\n",
" try:\n",
" with open(filePath, \"w\") as f:\n",
" json.dump(self.runs, f, indent=4)\n",
" except Exception as e:\n",
" print(e)\n",
" except Exception as e:\n",
" print(e)\n",
"\n",
" def saveDataToFile(self, filePath=\"../runtimestats.json\"):\n",
" try:\n",
" print(\"Saving Runs\")\n",
" with open(filePath, \"w+\") as f:\n",
" json.dump(self.runs, f, indent=4)\n",
" except FileNotFoundError:\n",
" print(\"Could not find file at {}\".format(filePath))\n",
" except Exception as e:\n",
" print(e)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{}\n",
"{'2023-1-11': {'run_1': {'start': 1673465959.694776, 'frequencies': [67, 65, 59, 62, 100], 'end': 1673475545.313309}, 'run_2': {'start': 1673469145.271416, 'end': 1673469136.691883, 'frequencies': [100, 99, 98, 87, 56, 56, 58, 67]}}, '2023-1-10': {'run_1': {'start': 1673465959.694776, 'frequencies': [67, 65, 59, 62], 'end': 1673469136.691883}, 'run_2': {'start': 1673469145.271416, 'end': 1673469136.691883}}, '2023-1-9': {'run_1': {'start': 1673465959.694776, 'frequencies': [67, 65, 59, 62], 'end': 1673469136.691883}, 'run_2': {'start': 1673469145.271416, 'end': 1673469136.691883}}}\n"
]
}
],
"source": [
"rts = RuntimeStats()\n",
"print(rts.runs)\n",
"path = \"/Users/nico/Documents/test/runtimestats.json\"\n",
"rts.loadDataFromFile(filePath=path)\n",
"print(rts.runs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.endRun()\n",
"print(rts.runs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.saveDataToFile(filePath=path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.startRun()\n",
"print(rts.runs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.countRunsDay()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2.66"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rts.calculateRunTimeDay(day=\"2023-1-11\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"11.08"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rts.calculateRunPercentDay(day=\"2023-1-11\")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.61"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rts.calculateRunPercentMultiDay()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.calculateRunTimeMultiDay()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rts.addHertzDataPoint(67)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"74.92\n",
"2023-1-10 missing frequency data for run_2\n",
"2023-1-9 missing frequency data for run_2\n",
"70.48\n"
]
}
],
"source": [
"print(rts.calculateAverageHertzDay(\"2023-1-11\"))\n",
"print(rts.calculateAverageHertzMultiDay())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"runs = {\"run_1\" : {}}\n",
"runs[\"run_1\"][\"start\"] = dt.timestamp(dt.now())\n",
"runs[\"run_1\"][\"end\"] = dt.timestamp(dt.now() + td(0,3600))\n",
"\n",
"runs[\"run_2\"] = {}\n",
"runs[\"run_2\"][\"start\"] = dt.timestamp(dt.now() + td(0,3600) +td(0,3600))\n",
"\n",
"runs[\"run_2\"][\"end\"] = dt.timestamp(dt.now() + td(0,3600) +td(0,3600) + td(0,3600))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"total_time = 0\n",
"for key in list(runs.keys()):\n",
" total_time = runs[key][\"end\"] - runs[key][\"start\"] + total_time"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(total_time)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"today = dt.today()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"{str(today.year)+\"-\"+str(today.month)+\"-\"+str(today.day): {\"run_1\": {\"start\": dt.timestamp(dt.now()), \"end\": dt.timestamp(dt.now()), \"hz\": [56,60,57,61,59,57,60]}}}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = [1,2,4,5]\n",
"b = [6,7,8,8,89]\n",
"c = []\n",
"c += a\n",
"c += b\n",
"print(math.fsum(c)/len(c))\n",
"print((math.fsum(a)/len(a) + math.fsum(b)/len(b))/2)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'that': {'is': 'a bigger test'}}\n"
]
}
],
"source": [
"t = {\"this\": \"test1\", \"that\": {\"is\": \"a bigger test\"}}\n",
"del t[\"this\"]\n",
"print(t)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "webkit",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "22238595996e71d7b27448e64f75d285aa95d1182295fdd30f75905446cf0091"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}