Part of the probelm could be that you seem to assume that the solenoid will push and pull, depending on the polarity of the drive (as does work with a DC motor). Solenoids generally have one-way actuation. When the coil is energised the core is pulled into the coil. A push solenoid will have a pin on one end of the core that moves out as the core moves into the coil. On a pull solenoid there is some dort of hook on the other end of the core (relative to a push configuration) that move toward the coil when energised.
See the datasheet
for the solenoid you have. It shows a pull version and a pull version.
Reversing polarity on the coil may move the core a little bit in the opposite direction, but it will not push the core out of the coil.
You use the force of the spring to more the core to the rest position and the coil current to move the core to the active position.
There are such things as bistable solenoids that can be energised to position A or position B and will stay there. These work by
a. Latching the core in the active position with a permanent magnet (or other latch)
b. having two coils/magnetic circuits (two directions of pull, two solenoids back-to-back)
c. using a permanent magnet (push-pull against the magnet).
Your solenoid is not bistable/latching.
This bistable solenoid
uses a permanent magnet to hold the core in the active position. Reversing the coil current cancels out the permanent magnet's holding field and the core is released to spring back.
Energise to unlock is the usual mode for door locks. Energise to hold is normal for magnetic catches that hold fire doors open. Consider what should happen if power fails.
If you need to hold the solenoid on for some time you will have to keep your script running in the background for the duration. If you call GPIO.cleanup() the outputs you configured revert to inputs and the solenoid will turn off.
ALternatively, just leave out the gpio.cleanup() and ignore the warning, AFAIK it only resets GPIO pin states and not calling it will simplyi leave the GPIO pins you assign in thier last programmed state when your program exits. If you have a separate lock scripts and unlock scripts don't use cleanup. Note that cleanup might do more than reset pins, so there may be situatiosn where you have to call it. If you are just doing some outputs you can probably skip it. It is good practice to clean up. A better approach is to have your program remain resident for as long as you need the IO, and then clean up on exit. Send messages to your program to get it to change the IO. You could use GPIO inputs, signals (e.g. HUP), pipes, sockets, files, serial or whatever to toggle between locked and unlocked states.