Let the SQL engine do the constraint check or execute a query to check the constraint beforehand
The best option is (b), from almost any perspective.  As mentioned in a comment, there is a multi-threading issue.  That means that option (a) doesn't even protect data integrity.  And that is a primary reason why you want data integrity checks inside the database, not outside it.
There are other reasons.  Consider performance.  Passing data into and out of the database takes effort.  There are multiple levels of protocol and data preparation, not to mention round trip, sequential communication from the database server.  One call has one such unit of overhead.  Two calls have two such units.
It is true that under some circumstances, a failed query can have a long clean-up period.  However, constraint checking for unique values is a single lookup in an index, which is both fast and has minimal overhead for cleaning up.  The extra overhead for handling the error should be tiny in comparison to the overhead for running the queries from the application -- both are small, one is much smaller.
If you had a query load where the inserts were really rare with respect to the comparison, then you might consider doing the check in the application.  It is probably a tiny bit faster to check to see if something exists using a SELECT  rather than using INSERT.  However, unless your query load is many such checks for each actual insert, I would go with checking in the database and move on to other issues.
Python application, standard web app.
If a particular request gets executed twice by error the second request will try to insert a row with an already existing primary key.  
What is the most sensible way to deal with it.
a) Execute a query to check if the primary key already exists and do the checking and error handling in the python app
b) Let the SQL engine reject the insertion with a constraint failure and use exception handling to handle it back in the app
From a speed perspective it might seem that a failed request will take the same amount of time as a successful one, making b faster because its only one request and not two.
However, when you take things in account like read-only db slaves and table write-locks and stuff like that things get fuzzy for my experience on scaling standard SQL databases.