Tinjau file berikut (sample_data.py
), yang mewakili data sampel yang Anda masukkan ke dalamvehicle-registration
tabel. File ini juga mengimpor dariamazon.ion
paket untuk menyediakan fungsi pembantu yang mengonversi, mengurai, dan mencetak data Amazon Ion.
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from datetime import datetime
from decimal import Decimal
from logging import basicConfig, getLogger, INFO
from amazon.ion.simple_types import IonPyBool, IonPyBytes, IonPyDecimal, IonPyDict, IonPyFloat, IonPyInt, IonPyList, \
IonPyNull, IonPySymbol, IonPyText, IonPyTimestamp
from amazon.ion.simpleion import dumps, loads
logger = getLogger(__name__)
basicConfig(level=INFO)
IonValue = (IonPyBool, IonPyBytes, IonPyDecimal, IonPyDict, IonPyFloat, IonPyInt, IonPyList, IonPyNull, IonPySymbol,
IonPyText, IonPyTimestamp)
class SampleData:
"""
Sample domain objects for use throughout this tutorial.
"""
DRIVERS_LICENSE = [
{
'PersonId': '',
'LicenseNumber': 'LEWISR261LL',
'LicenseType': 'Learner',
'ValidFromDate': datetime(2016, 12, 20),
'ValidToDate': datetime(2020, 11, 15)
},
{
'PersonId': '',
'LicenseNumber': 'LOGANB486CG',
'LicenseType': 'Probationary',
'ValidFromDate': datetime(2016, 4, 6),
'ValidToDate': datetime(2020, 11, 15)
},
{
'PersonId': '',
'LicenseNumber': '744 849 301',
'LicenseType': 'Full',
'ValidFromDate': datetime(2017, 12, 6),
'ValidToDate': datetime(2022, 10, 15)
},
{
'PersonId': '',
'LicenseNumber': 'P626-168-229-765',
'LicenseType': 'Learner',
'ValidFromDate': datetime(2017, 8, 16),
'ValidToDate': datetime(2021, 11, 15)
},
{
'PersonId': '',
'LicenseNumber': 'S152-780-97-415-0',
'LicenseType': 'Probationary',
'ValidFromDate': datetime(2015, 8, 15),
'ValidToDate': datetime(2021, 8, 21)
}
]
PERSON = [
{
'FirstName': 'Raul',
'LastName': 'Lewis',
'Address': '1719 University Street, Seattle, WA, 98109',
'DOB': datetime(1963, 8, 19),
'GovId': 'LEWISR261LL',
'GovIdType': 'Driver License'
},
{
'FirstName': 'Brent',
'LastName': 'Logan',
'DOB': datetime(1967, 7, 3),
'Address': '43 Stockert Hollow Road, Everett, WA, 98203',
'GovId': 'LOGANB486CG',
'GovIdType': 'Driver License'
},
{
'FirstName': 'Alexis',
'LastName': 'Pena',
'DOB': datetime(1974, 2, 10),
'Address': '4058 Melrose Street, Spokane Valley, WA, 99206',
'GovId': '744 849 301',
'GovIdType': 'SSN'
},
{
'FirstName': 'Melvin',
'LastName': 'Parker',
'DOB': datetime(1976, 5, 22),
'Address': '4362 Ryder Avenue, Seattle, WA, 98101',
'GovId': 'P626-168-229-765',
'GovIdType': 'Passport'
},
{
'FirstName': 'Salvatore',
'LastName': 'Spencer',
'DOB': datetime(1997, 11, 15),
'Address': '4450 Honeysuckle Lane, Seattle, WA, 98101',
'GovId': 'S152-780-97-415-0',
'GovIdType': 'Passport'
}
]
VEHICLE = [
{
'VIN': '1N4AL11D75C109151',
'Type': 'Sedan',
'Year': 2011,
'Make': 'Audi',
'Model': 'A5',
'Color': 'Silver'
},
{
'VIN': 'KM8SRDHF6EU074761',
'Type': 'Sedan',
'Year': 2015,
'Make': 'Tesla',
'Model': 'Model S',
'Color': 'Blue'
},
{
'VIN': '3HGGK5G53FM761765',
'Type': 'Motorcycle',
'Year': 2011,
'Make': 'Ducati',
'Model': 'Monster 1200',
'Color': 'Yellow'
},
{
'VIN': '1HVBBAANXWH544237',
'Type': 'Semi',
'Year': 2009,
'Make': 'Ford',
'Model': 'F 150',
'Color': 'Black'
},
{
'VIN': '1C4RJFAG0FC625797',
'Type': 'Sedan',
'Year': 2019,
'Make': 'Mercedes',
'Model': 'CLK 350',
'Color': 'White'
}
]
VEHICLE_REGISTRATION = [
{
'VIN': '1N4AL11D75C109151',
'LicensePlateNumber': 'LEWISR261LL',
'State': 'WA',
'City': 'Seattle',
'ValidFromDate': datetime(2017, 8, 21),
'ValidToDate': datetime(2020, 5, 11),
'PendingPenaltyTicketAmount': Decimal('90.25'),
'Owners': {
'PrimaryOwner': {'PersonId': ''},
'SecondaryOwners': []
}
},
{
'VIN': 'KM8SRDHF6EU074761',
'LicensePlateNumber': 'CA762X',
'State': 'WA',
'City': 'Kent',
'PendingPenaltyTicketAmount': Decimal('130.75'),
'ValidFromDate': datetime(2017, 9, 14),
'ValidToDate': datetime(2020, 6, 25),
'Owners': {
'PrimaryOwner': {'PersonId': ''},
'SecondaryOwners': []
}
},
{
'VIN': '3HGGK5G53FM761765',
'LicensePlateNumber': 'CD820Z',
'State': 'WA',
'City': 'Everett',
'PendingPenaltyTicketAmount': Decimal('442.30'),
'ValidFromDate': datetime(2011, 3, 17),
'ValidToDate': datetime(2021, 3, 24),
'Owners': {
'PrimaryOwner': {'PersonId': ''},
'SecondaryOwners': []
}
},
{
'VIN': '1HVBBAANXWH544237',
'LicensePlateNumber': 'LS477D',
'State': 'WA',
'City': 'Tacoma',
'PendingPenaltyTicketAmount': Decimal('42.20'),
'ValidFromDate': datetime(2011, 10, 26),
'ValidToDate': datetime(2023, 9, 25),
'Owners': {
'PrimaryOwner': {'PersonId': ''},
'SecondaryOwners': []
}
},
{
'VIN': '1C4RJFAG0FC625797',
'LicensePlateNumber': 'TH393F',
'State': 'WA',
'City': 'Olympia',
'PendingPenaltyTicketAmount': Decimal('30.45'),
'ValidFromDate': datetime(2013, 9, 2),
'ValidToDate': datetime(2024, 3, 19),
'Owners': {
'PrimaryOwner': {'PersonId': ''},
'SecondaryOwners': []
}
}
]
def convert_object_to_ion(py_object):
"""
Convert a Python object into an Ion object.
:type py_object: object
:param py_object: The object to convert.
:rtype: :py:class:`amazon.ion.simple_types.IonPyValue`
:return: The converted Ion object.
"""
ion_object = loads(dumps(py_object))
return ion_object
def to_ion_struct(key, value):
"""
Convert the given key and value into an Ion struct.
:type key: str
:param key: The key which serves as an unique identifier.
:type value: str
:param value: The value associated with a given key.
:rtype: :py:class:`amazon.ion.simple_types.IonPyDict`
:return: The Ion dictionary object.
"""
ion_struct = dict()
ion_struct[key] = value
return loads(str(ion_struct))
def get_document_ids(transaction_executor, table_name, field, value):
"""
Gets the document IDs from the given table.
:type transaction_executor: :py:class:`pyqldb.execution.executor.Executor`
:param transaction_executor: An Executor object allowing for execution of statements within a transaction.
:type table_name: str
:param table_name: The table name to query.
:type field: str
:param field: A field to query.
:type value: str
:param value: The key of the given field.
:rtype: list
:return: A list of document IDs.
"""
query = "SELECT id FROM {} AS t BY id WHERE t.{} = ?".format(table_name, field)
cursor = transaction_executor.execute_statement(query, convert_object_to_ion(value))
return list(map(lambda table: table.get('id'), cursor))
def get_document_ids_from_dml_results(result):
"""
Return a list of modified document IDs as strings from DML results.
:type result: :py:class:`pyqldb.cursor.buffered_cursor.BufferedCursor`
:param: result: The result set from DML operation.
:rtype: list
:return: List of document IDs.
"""
ret_val = list(map(lambda x: x.get('documentId'), result))
return ret_val
def print_result(cursor):
"""
Pretty print the result set. Returns the number of documents in the result set.
:type cursor: :py:class:`pyqldb.cursor.stream_cursor.StreamCursor`/
:py:class:`pyqldb.cursor.buffered_cursor.BufferedCursor`
:param cursor: An instance of the StreamCursor or BufferedCursor class.
:rtype: int
:return: Number of documents in the result set.
"""
result_counter = 0
for row in cursor:
# Each row would be in Ion format.
print_ion(row)
result_counter += 1
return result_counter
def print_ion(ion_value):
"""
Pretty print an Ion Value.
:type ion_value: :py:class:`amazon.ion.simple_types.IonPySymbol`
:param ion_value: Any Ion Value to be pretty printed.
"""
logger.info(dumps(ion_value, binary=False, indent=' ', omit_version_marker=True))
get_document_ids
Fungsi ini menjalankan query yang mengembalikan ID dokumen sistem-ditugaskan dari tabel. Untuk mempelajari selengkapnya, lihat Menggunakan klausa BY untuk query ID dokumen.
Gunakan program berikut (insert_document.py
) untuk memasukkan data sampel ke dalam tabel Anda.
3.x
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# This code expects that you have AWS credentials setup per:
# https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
from logging import basicConfig, getLogger, INFO
from pyqldbsamples.constants import Constants
from pyqldbsamples.model.sample_data import convert_object_to_ion, SampleData, get_document_ids_from_dml_results
from pyqldbsamples.connect_to_ledger import create_qldb_driver
logger = getLogger(__name__)
basicConfig(level=INFO)
def update_person_id(document_ids):
"""
Update the PersonId value for DriversLicense records and the PrimaryOwner value for VehicleRegistration records.
:type document_ids: list
:param document_ids: List of document IDs.
:rtype: list
:return: Lists of updated DriversLicense records and updated VehicleRegistration records.
"""
new_drivers_licenses = SampleData.DRIVERS_LICENSE.copy()
new_vehicle_registrations = SampleData.VEHICLE_REGISTRATION.copy()
for i in range(len(SampleData.PERSON)):
drivers_license = new_drivers_licenses[i]
registration = new_vehicle_registrations[i]
drivers_license.update({'PersonId': str(document_ids[i])})
registration['Owners']['PrimaryOwner'].update({'PersonId': str(document_ids[i])})
return new_drivers_licenses, new_vehicle_registrations
def insert_documents(driver, table_name, documents):
"""
Insert the given list of documents into a table in a single transaction.
:type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
:param driver: An instance of the QldbDriver class.
:type table_name: str
:param table_name: Name of the table to insert documents into.
:type documents: list
:param documents: List of documents to insert.
:rtype: list
:return: List of documents IDs for the newly inserted documents.
"""
logger.info('Inserting some documents in the {} table...'.format(table_name))
statement = 'INSERT INTO {} ?'.format(table_name)
cursor = driver.execute_lambda(lambda executor: executor.execute_statement(statement,
convert_object_to_ion(documents)))
list_of_document_ids = get_document_ids_from_dml_results(cursor)
return list_of_document_ids
def update_and_insert_documents(driver):
"""
Handle the insertion of documents and updating PersonIds.
:type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
:param driver: An instance of the QldbDriver class.
"""
list_ids = insert_documents(driver, Constants.PERSON_TABLE_NAME, SampleData.PERSON)
logger.info("Updating PersonIds for 'DriversLicense' and PrimaryOwner for 'VehicleRegistration'...")
new_licenses, new_registrations = update_person_id(list_ids)
insert_documents(driver, Constants.VEHICLE_TABLE_NAME, SampleData.VEHICLE)
insert_documents(driver, Constants.VEHICLE_REGISTRATION_TABLE_NAME, new_registrations)
insert_documents(driver, Constants.DRIVERS_LICENSE_TABLE_NAME, new_licenses)
def main(ledger_name=Constants.LEDGER_NAME):
"""
Insert documents into a table in a QLDB ledger.
"""
try:
with create_qldb_driver(ledger_name) as driver:
# An INSERT statement creates the initial revision of a document with a version number of zero.
# QLDB also assigns a unique document identifier in GUID format as part of the metadata.
update_and_insert_documents(driver)
logger.info('Documents inserted successfully!')
except Exception as e:
logger.exception('Error inserting or updating documents.')
raise e
if __name__ == '__main__':
main()
2.x
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# This code expects that you have AWS credentials setup per:
# https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
from logging import basicConfig, getLogger, INFO
from pyqldbsamples.constants import Constants
from pyqldbsamples.model.sample_data import convert_object_to_ion, SampleData, get_document_ids_from_dml_results
from pyqldbsamples.connect_to_ledger import create_qldb_session
logger = getLogger(__name__)
basicConfig(level=INFO)
def update_person_id(document_ids):
"""
Update the PersonId value for DriversLicense records and the PrimaryOwner value for VehicleRegistration records.
:type document_ids: list
:param document_ids: List of document IDs.
:rtype: list
:return: Lists of updated DriversLicense records and updated VehicleRegistration records.
"""
new_drivers_licenses = SampleData.DRIVERS_LICENSE.copy()
new_vehicle_registrations = SampleData.VEHICLE_REGISTRATION.copy()
for i in range(len(SampleData.PERSON)):
drivers_license = new_drivers_licenses[i]
registration = new_vehicle_registrations[i]
drivers_license.update({'PersonId': str(document_ids[i])})
registration['Owners']['PrimaryOwner'].update({'PersonId': str(document_ids[i])})
return new_drivers_licenses, new_vehicle_registrations
def insert_documents(transaction_executor, table_name, documents):
"""
Insert the given list of documents into a table in a single transaction.
:type transaction_executor: :py:class:`pyqldb.execution.executor.Executor`
:param transaction_executor: An Executor object allowing for execution of statements within a transaction.
:type table_name: str
:param table_name: Name of the table to insert documents into.
:type documents: list
:param documents: List of documents to insert.
:rtype: list
:return: List of documents IDs for the newly inserted documents.
"""
logger.info('Inserting some documents in the {} table...'.format(table_name))
statement = 'INSERT INTO {} ?'.format(table_name)
cursor = transaction_executor.execute_statement(statement, convert_object_to_ion(documents))
list_of_document_ids = get_document_ids_from_dml_results(cursor)
return list_of_document_ids
def update_and_insert_documents(transaction_executor):
"""
Handle the insertion of documents and updating PersonIds all in a single transaction.
:type transaction_executor: :py:class:`pyqldb.execution.executor.Executor`
:param transaction_executor: An Executor object allowing for execution of statements within a transaction.
"""
list_ids = insert_documents(transaction_executor, Constants.PERSON_TABLE_NAME, SampleData.PERSON)
logger.info("Updating PersonIds for 'DriversLicense' and PrimaryOwner for 'VehicleRegistration'...")
new_licenses, new_registrations = update_person_id(list_ids)
insert_documents(transaction_executor, Constants.VEHICLE_TABLE_NAME, SampleData.VEHICLE)
insert_documents(transaction_executor, Constants.VEHICLE_REGISTRATION_TABLE_NAME, new_registrations)
insert_documents(transaction_executor, Constants.DRIVERS_LICENSE_TABLE_NAME, new_licenses)
if __name__ == '__main__':
"""
Insert documents into a table in a QLDB ledger.
"""
try:
with create_qldb_session() as session:
# An INSERT statement creates the initial revision of a document with a version number of zero.
# QLDB also assigns a unique document identifier in GUID format as part of the metadata.
session.execute_lambda(lambda executor: update_and_insert_documents(executor),
lambda retry_attempt: logger.info('Retrying due to OCC conflict...'))
logger.info('Documents inserted successfully!')
except Exception:
logger.exception('Error inserting or updating documents.')
Program ini menunjukkan bagaimana memanggilexecute_statement
fungsi dengan nilai-nilai parameter. Anda dapat melewati parameter data selain pernyataan PartiQL yang ingin Anda jalankan. Gunakan tanda tanya (
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# This code expects that you have AWS credentials setup per:
# https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
from logging import basicConfig, getLogger, INFO
from pyqldbsamples.constants import Constants
from pyqldbsamples.model.sample_data import convert_object_to_ion, SampleData, get_document_ids_from_dml_results
from pyqldbsamples.connect_to_ledger import create_qldb_driver
logger = getLogger(__name__)
basicConfig(level=INFO)
def update_person_id(document_ids):
"""
Update the PersonId value for DriversLicense records and the PrimaryOwner value for VehicleRegistration records.
:type document_ids: list
:param document_ids: List of document IDs.
:rtype: list
:return: Lists of updated DriversLicense records and updated VehicleRegistration records.
"""
new_drivers_licenses = SampleData.DRIVERS_LICENSE.copy()
new_vehicle_registrations = SampleData.VEHICLE_REGISTRATION.copy()
for i in range(len(SampleData.PERSON)):
drivers_license = new_drivers_licenses[i]
registration = new_vehicle_registrations[i]
drivers_license.update({'PersonId': str(document_ids[i])})
registration['Owners']['PrimaryOwner'].update({'PersonId': str(document_ids[i])})
return new_drivers_licenses, new_vehicle_registrations
def insert_documents(driver, table_name, documents):
"""
Insert the given list of documents into a table in a single transaction.
:type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
:param driver: An instance of the QldbDriver class.
:type table_name: str
:param table_name: Name of the table to insert documents into.
:type documents: list
:param documents: List of documents to insert.
:rtype: list
:return: List of documents IDs for the newly inserted documents.
"""
logger.info('Inserting some documents in the {} table...'.format(table_name))
statement = 'INSERT INTO {} ?'.format(table_name)
cursor = driver.execute_lambda(lambda executor: executor.execute_statement(statement,
convert_object_to_ion(documents)))
list_of_document_ids = get_document_ids_from_dml_results(cursor)
return list_of_document_ids
def update_and_insert_documents(driver):
"""
Handle the insertion of documents and updating PersonIds.
:type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
:param driver: An instance of the QldbDriver class.
"""
list_ids = insert_documents(driver, Constants.PERSON_TABLE_NAME, SampleData.PERSON)
logger.info("Updating PersonIds for 'DriversLicense' and PrimaryOwner for 'VehicleRegistration'...")
new_licenses, new_registrations = update_person_id(list_ids)
insert_documents(driver, Constants.VEHICLE_TABLE_NAME, SampleData.VEHICLE)
insert_documents(driver, Constants.VEHICLE_REGISTRATION_TABLE_NAME, new_registrations)
insert_documents(driver, Constants.DRIVERS_LICENSE_TABLE_NAME, new_licenses)
def main(ledger_name=Constants.LEDGER_NAME):
"""
Insert documents into a table in a QLDB ledger.
"""
try:
with create_qldb_driver(ledger_name) as driver:
# An INSERT statement creates the initial revision of a document with a version number of zero.
# QLDB also assigns a unique document identifier in GUID format as part of the metadata.
update_and_insert_documents(driver)
logger.info('Documents inserted successfully!')
except Exception as e:
logger.exception('Error inserting or updating documents.')
raise e
if __name__ == '__main__':
main()
0) sebagai placeholder variabel dalam string pernyataan Anda.