'Prepares a query string, returning a :class:`~cassandra.query.PreparedStatement`
instance which can be used as follows::
>>> session = cluster.connect("mykeyspace")
>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
>>> prepared = session.prepare(query)
>>> session.execute(prepared, (user.id, user.name, user.age))
Or you may bind values to the prepared statement ahead of time::
>>> prepared = session.prepare(query)
>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
>>> session.execute(bound_stmt)
Of course, prepared statements may (and should) be reused::
>>> prepared = session.prepare(query)
>>> for user in users:
...     bound = prepared.bind((user.id, user.name, user.age))
...     session.execute(bound)
**Important**: PreparedStatements should be prepared only once.
Preparing the same query more than once will likely affect performance.
`custom_payload` is a key value map to be passed along with the prepare
message. See :ref:`custom_payload`.'

def prepare(self, query, custom_payload=None):

    message = PrepareMessage(query=query)
    future = ResponseFuture(self, message, query=None, timeout=self.default_timeout)
    try:
        future.send_request()
        (query_id, bind_metadata, pk_indexes, result_metadata) = future.result()
    except Exception:
        log.exception('Error    preparing    query:')
        raise
    prepared_statement = PreparedStatement.from_message(query_id, bind_metadata, pk_indexes, self.cluster.metadata, query, self.keyspace, self._protocol_version, result_metadata)
    prepared_statement.custom_payload = future.custom_payload
    self.cluster.add_prepared(query_id, prepared_statement)
    if self.cluster.prepare_on_all_hosts:
        host = future._current_host
        try:
            self.prepare_on_all_hosts(prepared_statement.query_string, host)
        except Exception:
            log.exception('Error    preparing    query    on    all    hosts:')
    return prepared_statement
