I'll assume you already have a private key available, using something like extracting a private key from a geth keyfile, and that you are using Web3.py v4.2.0.
The general approach is to:
- construct your contract with any initialization arguments
- build the transaction for the contract constructor
- sign the transaction with your private key
- broadcast the signed transaction
- wait for the transaction to be mined
One convenient way to build the transaction locally is to use the constructor() method on a contract object. For example:
deploy_txn = my_contract.constructor(*init_args).buildTransaction()
Then, sign the transaction locally:
signed = w3.eth.account.signTransaction(deploy_txn, private_key)
Finally, broadcast the transaction, and wait for it to be mined:
txn_hash = w3.eth.sendRawTransaction(signed.rawTransaction)
txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
To use the contract, you can rebuild the contract object with its new address. The address of your new contract is available at txn_receipt['contractAddress'].