# NameError: global name "" not defined

**URL:** <https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958>\
**Category:** Ignition\
**Created:** [April 3, 2023, 9:19am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958 "2023-04-03T09:19:37Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![AD\_Corporation](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ad_corporation/32/45605_2.png) [@AD\_Corporation](https://forum.inductiveautomation.com/u/AD_Corporation)\
**Post date:** [April 3, 2023, 9:19am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/1 "2023-04-03T09:19:37Z")

</div>

![bug ignition](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/b/5b7f4f20d31442150567a9c873441d07e651286a.png)

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [April 3, 2023, 9:30am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/2 "2023-04-03T09:30:41Z")

</div>

I believe this is the answer you are looking for:

> [@Run Scripts from Tag Change](https://forum.inductiveautomation.com/t/run-scripts-from-tag-change/34579/2):
>
> Sure they can - set the ‘gateway scripting project’ in Configure -\> Gateway Settings. Or, as @pturmel will tell you, use project-level gateway tag change scripts over individual tag events.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [April 3, 2023, 10:27am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/3 "2023-04-03T10:27:32Z")

</div>

Because scope.

This is probably explained in the thread @justinedwards.jle linked, but to make things short here:  
Tags do not belong to a project. They're on the gateway, which exposes them to your projects.

Since they're not part of a project, they don't have access to scripts defined in a project library... unless that project has been designated as the gateway Scripting Project.

So, you can either put the scripts your tags need access to in the Global Scripting Project, or use a gateway event tag change script instead. Since those belong to a project, they have access to the project library, and can be used to trigger scripts when tags change.

---

<div class="post-metadata">

**Author:** ![AD\_Corporation](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ad_corporation/32/45605_2.png) [@AD\_Corporation](https://forum.inductiveautomation.com/u/AD_Corporation)\
**Post date:** [April 3, 2023, 1:45pm UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/4 "2023-04-03T13:45:44Z")

</div>

![bug ignition solved](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/2/722929c34179905299b1404ad3e8fafbd427631c.png)  
Gateway scripting project filled with the design project name solve the problem

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 3, 2023, 1:48pm UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/5 "2023-04-03T13:48:02Z")

</div>

Keep in mind that you only get one Gateway Scripting Project. In a multi-project gateway, take care to segregate all tag functionality from other projects.

---

<div class="post-metadata">

**Author:** ![Rahul\_Bhakte1](https://avatars.discourse-cdn.com/v4/letter/r/c89c15/32.png) [@Rahul\_Bhakte1](https://forum.inductiveautomation.com/u/Rahul_Bhakte1)\
**Post date:** [July 29, 2024, 10:30am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/6 "2024-07-29T10:30:25Z")

</div>

Hello @pascal.fragnoud,

I am trying to run script on gateway tag change script but giving me NameError.

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/8/f88ce4182089d6350a3669abeaedcd3f9c70c19f.png)

part of code is:

```python
old_dict = {(item[1], item[2], item[3]): item for item in oldList}
new_dict = {(item[1], item[2], item[3]): item for item in newList}
new_records = {key: value for key, value in new_dict.items() if key not in old_dict}

```

Error in Line 3: Caused by: org.python.core.PyException: NameError: global name 'old\_dict' is not defined.

When I run the same script on script consol, it works perfectly.  
I am not sure what I am missing here.  
Please suggest.  
Thanks in advance.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 29, 2024, 10:35am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/7 "2024-07-29T10:35:10Z")

</div>

Show us the full script.

But you should start by putting the code in a library function, then calling that function from the gateway event.  
Get into the habit of not coding in gateway events.

---

<div class="post-metadata">

**Author:** ![Rahul\_Bhakte1](https://avatars.discourse-cdn.com/v4/letter/r/c89c15/32.png) [@Rahul\_Bhakte1](https://forum.inductiveautomation.com/u/Rahul_Bhakte1)\
**Post date:** [July 29, 2024, 11:37am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/8 "2024-07-29T11:37:21Z")

</div>

Bingo!!!  
That worked when I put the script on project library and called it from Tag change script.  
Thanks a lot.  
I will keep this habit in future.  
Great day 🙂

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [July 29, 2024, 2:12pm UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/9 "2024-07-29T14:12:08Z")

</div>

well i doubt that was the solution though, my guess is some indenting were wrong that got fixed by copying it to somewhere else...

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 29, 2024, 2:24pm UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/10 "2024-07-29T14:24:07Z")

</div>

That would result in an `IndentationError`, not a `NameError`, though I stopped trying to figure out what's going on in gateway events ;p

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [July 29, 2024, 2:39pm UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/11 "2024-07-29T14:39:56Z")

</div>

Depends it could still be funtional code but the declaration is on a wrong indent  
Like this... would result in a no defined, can't really think of something else

```python
if False:
  something something..
  old_dict = {(item[1], item[2], item[3]): item for item in oldList}
new_dict = {(item[1], item[2], item[3]): item for item in newList}
new_records = {key: value for key, value in new_dict.items() if key not in old_dict}

```

but yh no point in making sense of it now if op didn't post the full code and it works now xd

---

<div class="post-metadata">

**Author:** ![Rahul\_Bhakte1](https://avatars.discourse-cdn.com/v4/letter/r/c89c15/32.png) [@Rahul\_Bhakte1](https://forum.inductiveautomation.com/u/Rahul_Bhakte1)\
**Post date:** [July 30, 2024, 5:57am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/12 "2024-07-30T05:57:44Z")

</div>

Hello,  
FYI, this is the full code.

```python
newDefects = system.tag.readBlocking(["[Machine_Defects]Assembly/BAP/New_Log"])[0].value
oldDefects = system.tag.readBlocking(["[Machine_Defects]Assembly/BAP/Old_Log"])[0].value

oldList = []
newList = []

if oldDefects.getRowCount() != 0:
	oldList = [[oldDefects.getValueAt(i, "Engine"), oldDefects.getValueAt(i, "SN"), oldDefects.getValueAt(i, "Date"),
				oldDefects.getValueAt(i, "Time"), oldDefects.getValueAt(i, "Position"), oldDefects.getValueAt(i, "Z"),
				oldDefects.getValueAt(i, "X"),oldDefects.getValueAt(i, "Y"),oldDefects.getValueAt(i, "X_final"),oldDefects.getValueAt(i, "Y_final"),
				oldDefects.getValueAt(i, "Engine_type"),oldDefects.getValueAt(i, "Searching"),oldDefects.getValueAt(i, "Piston"),oldDefects.getValueAt(i, "Tightening"),
				oldDefects.getValueAt(i, "Insertion"),oldDefects.getValueAt(i, "Insertion_pos"),oldDefects.getValueAt(i, "Insertion_pos_min"),oldDefects.getValueAt(i, "Insertion_pos_max"),
				oldDefects.getValueAt(i, "Con_rod"),oldDefects.getValueAt(i, "Caps"),oldDefects.getValueAt(i, "Ref_table"),oldDefects.getValueAt(i, "OPEN_1"),
				oldDefects.getValueAt(i, "OPEN_2"),oldDefects.getValueAt(i, "CLOSE_1"),oldDefects.getValueAt(i, "CLOSE_2"),oldDefects.getValueAt(i, "CARRIER"),
				oldDefects.getValueAt(i, "Double_attempt"),oldDefects.getValueAt(i, "Stroke_1"),oldDefects.getValueAt(i, "Stroke_2"),oldDefects.getValueAt(i, "DEF Serrage piston"),
				oldDefects.getValueAt(i, "DEF Insertion"),oldDefects.getValueAt(i, "ATT plus de demande d?pose pieds 5"),oldDefects.getValueAt(i, "ATT abs demande huilage 5s"),oldDefects.getValueAt(i, "DateAndTime"),
				oldDefects.getValueAt(i, "DateAndTime_end"),oldDefects.getValueAt(i, "Duration"),oldDefects.getValueAt(i, "Day"),oldDefects.getValueAt(i, "Month"),
				oldDefects.getValueAt(i, "Year"),oldDefects.getValueAt(i, "Week"),oldDefects.getValueAt(i, "X_diff"),oldDefects.getValueAt(i, "Y_diff"),
				oldDefects.getValueAt(i, "Shift_type"),oldDefects.getValueAt(i, "Shift"),oldDefects.getValueAt(i, "Errorcat"),oldDefects.getValueAt(i, "SearchingGroup"),oldDefects.getValueAt(i, "Last_piston"),
				oldDefects.getValueAt(i, "Piston_left"),oldDefects.getValueAt(i, "Cyl_number"),oldDefects.getValueAt(i, "Cyl_position"),oldDefects.getValueAt(i, "Status")] 
				for i in range(oldDefects.getRowCount())]
				
if newDefects.getRowCount() != 0:	
	newList = [[newDefects.getValueAt(i, "Engine"), newDefects.getValueAt(i, "SN"), newDefects.getValueAt(i, "Date"),
				newDefects.getValueAt(i, "Time"), newDefects.getValueAt(i, "Position"), newDefects.getValueAt(i, "Z"),
				newDefects.getValueAt(i, "X"),newDefects.getValueAt(i, "Y"),newDefects.getValueAt(i, "X_final"),newDefects.getValueAt(i, "Y_final"),
				newDefects.getValueAt(i, "Engine_type"),newDefects.getValueAt(i, "Searching"),newDefects.getValueAt(i, "Piston"),newDefects.getValueAt(i, "Tightening"),
				newDefects.getValueAt(i, "Insertion"),newDefects.getValueAt(i, "Insertion_pos"),newDefects.getValueAt(i, "Insertion_pos_min"),newDefects.getValueAt(i, "Insertion_pos_max"),
				newDefects.getValueAt(i, "Con_rod"),newDefects.getValueAt(i, "Caps"),newDefects.getValueAt(i, "Ref_table"),newDefects.getValueAt(i, "OPEN_1"),
				newDefects.getValueAt(i, "OPEN_2"),newDefects.getValueAt(i, "CLOSE_1"),newDefects.getValueAt(i, "CLOSE_2"),newDefects.getValueAt(i, "CARRIER"),
				newDefects.getValueAt(i, "Double_attempt"),newDefects.getValueAt(i, "Stroke_1"),newDefects.getValueAt(i, "Stroke_2"),newDefects.getValueAt(i, "DEF Serrage piston"),
				newDefects.getValueAt(i, "DEF Insertion"),newDefects.getValueAt(i, "ATT plus de demande d?pose pieds 5"),newDefects.getValueAt(i, "ATT abs demande huilage 5s"),newDefects.getValueAt(i, "DateAndTime"),
				newDefects.getValueAt(i, "DateAndTime_end"),newDefects.getValueAt(i, "Duration"),newDefects.getValueAt(i, "Day"),newDefects.getValueAt(i, "Month"),
				newDefects.getValueAt(i, "Year"),newDefects.getValueAt(i, "Week"),newDefects.getValueAt(i, "X_diff"),newDefects.getValueAt(i, "Y_diff"),
				newDefects.getValueAt(i, "Shift_type"),newDefects.getValueAt(i, "Shift"),newDefects.getValueAt(i, "Errorcat"),newDefects.getValueAt(i, "SearchingGroup"),newDefects.getValueAt(i, "Last_piston"),
				newDefects.getValueAt(i, "Piston_left"),newDefects.getValueAt(i, "Cyl_number"),newDefects.getValueAt(i, "Cyl_position"),newDefects.getValueAt(i, "Status")] 
				for i in range(newDefects.getRowCount())]

# Convert old and new lists to dictionaries group by (SN, Date, Time) as keys
old_dict = {(item[1], item[2], item[3]): item for item in oldList}
new_dict = {(item[1], item[2], item[3]): item for item in newList}

new_records = {key: value for key, value in new_dict.items() if key not in old_dict}

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 30, 2024, 6:22am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/13 "2024-07-30T06:22:07Z")

</div>

I assume `oldList` and `newList` contain all the columns in the `newDefects` and `oldDefects` datasets ?  
This should do the same thing:

```python
new_defects, old_defects = [qv.value for qv in system.tag.readBlocking(["[Machine_Defects]Assembly/BAP/New_Log", "[Machine_Defects]Assembly/BAP/Old_Log"])]

old_dict = {
	(v['SN'], v['Date'], v['Time']): v
	for v in system.dataset.toPyDataSet(old_defects)
}

new_records = {
	(v['SN'], v['Date'], v['Time']): v
	for v in system.dataset.toPyDataSet(new_defects)
		if (v['SN'], v['Date'], v['Time']) not in old_dict
}

```

You may need to wrap the `v` in a `list()` call if whatever you use that for doesn't accept the row wrapper v actually is.

A few notes:

- read tags in bulk.
- you don't need to check if a list is empty before iterating through it. If it's empty, the resulting list will also be empty, so you don't need to initialize an empty list and wrap the comprehension in an if statement.

---

<div class="post-metadata">

**Author:** ![Rahul\_Bhakte1](https://avatars.discourse-cdn.com/v4/letter/r/c89c15/32.png) [@Rahul\_Bhakte1](https://forum.inductiveautomation.com/u/Rahul_Bhakte1)\
**Post date:** [July 30, 2024, 7:29am UTC](https://forum.inductiveautomation.com/t/nameerror-global-name-not-defined/71958/14 "2024-07-30T07:29:02Z")

</div>

Thank you @pascal.fragnoud for the very optimized code,

That worked like a snap of a finger 😉

Now this is my updated code which looks very efficient.

```python
new_defects, old_defects = [qv.value for qv in system.tag.readBlocking(["[Machine_Defects]Assembly/BAP/New_Log", "[Machine_Defects]Assembly/BAP/Old_Log"])]	
old_dict = {
	(v['SN'], v['Date'], v['Time']): v
	for v in system.dataset.toPyDataSet(old_defects)
}

new_records = {
	(v['SN'], v['Date'], v['Time']): v
	for v in system.dataset.toPyDataSet(new_defects)
		if (v['SN'], v['Date'], v['Time']) not in old_dict
}

query = '''INSERT INTO Bap (Engine,SN,Date,Time,Position,Z,X,Y,X_final,Y_final,Engine_type,Searching,Piston,Tightening,Insertion,Insertion_pos,Insertion_pos_min,Insertion_pos_max,Con_rod,Caps,Ref_table,OPEN_1,OPEN_2,CLOSE_1,CLOSE_2,CARRIER,Double_attempt,Stroke_1,Stroke_2,DEF_Serrage_piston,DEF_Insertion,ATT_plus_de_demande_dpose_pieds_5,ATT_abs_demande_huilage_5s,DateAndTime,DateAndTime_end,Duration,Day,Month,Year,Week,X_diff,Y_diff,Shift_type,Shift,Errorcat,SearchingGroup,Last_piston,Piston_left,Cyl_number,Cyl_position,Status,Piston_top_csv, Inserted_On) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'''
		
if len(new_records) > 0:
	for item in new_records.values():
		args = list(item)
		args.append('') #Piston_top_csv
		args.append(system.date.now())	#Inserted_On
		system.db.runPrepUpdate(query, args, 'DB')

	system.tag.writeBlocking("[Machine_Defects]Assembly/BAP/Old_Log", [new_defects])

```
