There are some different ways of achieving this. All of them depend on at least some provision in your code. There is no way of doing that exclusively in the Operating System level.
I will show two different "classes" of ways, both involve creating entries on the file system.
Python Only Lockfile
You can find two different ways of doing that in a bash script (conceptually the same) here and here. Can can use the same idea in a Python code, the bash shell script language is just for demonstrating the concept.
The idea is to work with a file on the file system that is created when the process starts, and a way of determining whether, when the process starts and find such file on the file system, if the other process that created it is still alive.
Of course you should remember to remove that file on exit, if possible (if not terminated by a -9 or something).
OS File Locking
In this approach your code will request a file lock from the Operating System, and, if succeeds, will hold the lock on the file until that instance of the program exits. If instance B is unable to achieve a lock, that means that one other instance A has the lock, so your instance B should exit.
You can find examples of that approach in Python here.
The one answer on that question that uses zc.lockfile seems the most adequate to me.
From zc.lockfile's manual:
The ZODB lock_file module provides support for creating file system locks. These are locks that are implemented with lock files and OS-provided locking facilities. To create a lock, instantiate a LockFile object with a file name:
>>> import zc.lockfile
>>> lock = zc.lockfile.LockFile('lock')
If we try to lock the same name, we'll get a lock error:
>>> import zope.testing.loggingsupport
>>> handler = zope.testing.loggingsupport.InstalledHandler('zc.lockfile')
... except zc.lockfile.LockError:
... print("Can't lock file")
Can't lock file
>>> for record in handler.records: # doctest: +ELLIPSIS
... print(record.levelname+' '+record.getMessage())
ERROR Error locking file lock; pid=...