Archive for the ‘Python 3.x’ Category
Using Python’s getopt
A couple of my students wanted me to write a switch and parameter handler for Python scripts. I wrote it just to show them it’s possible but I also show them how to do it correctly with the Python getopt library, which was soft-deprecated in Python 3.13 and replaced by the Python argparse library. The debate is which one I show you first in the blog.
This is the getops.py script that uses Python’s getopt library. There is a small trick to the options and long options values. You append a colon (:) to the option when it has a value, and append an equal (=) to the long option when it has a value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #!/usr/bin/python # Import libraries. import getopt, sys import mysql.connector from mysql.connector import errorcode # Define local function. def help(): # Declare display string. display = \ """ Program Help +---------------+-------------+-------------------+ | -h --help | | Help switch. | | -o --output | output_file | Output file name. | | -q --query | query_file | Query file name. | | -v --verbose | | Verbose switch. | +---------------+-------------+-------------------+""" # Return string. return display # ============================================================ # Set local variables for switch and parameter placeholders. # ============================================================ display = False log = [] output_file = '' query_file = '' verbose = False opts = "ho:q:v" long_opts = ["help","output=","query=","verbose"] # ============================================================ # Capture argument list minus the program name. # ============================================================ args = sys.argv[1:] # ============================================================ # Use a try-except block. # ============================================================ try: # Assign the results of the getopt function. params, values = getopt.getopt(args, opts, long_opts) # Loop through the parameters. for curr_param, curr_value in params: if curr_param in ("-h","--help"): print(help()) elif curr_param in ("-o","--output"): output_file = curr_value elif curr_param in ("-q","--query"): query_file = curr_value elif curr_param in ("-v","--verbose"): verbose = True # Append entry to log. log.append('[' + curr_param + '][' + curr_value + ']') # Print verbose parameter handling. if verbose: print(" Parameter Diagnostics\n-------------------------") for i in log: print(i) # Exception block. except getopt.GetoptError as e: # output error, and return with an error code print (str(e)) |
You can run the program in Linux or Unix with the following syntax provided that you’ve already set the parameters to 755. That means granting the file owner with read, write, and execute privileges, and group and other with read and execute privileges.
./getopts.py -h -o output.txt -q query.sql -v |
It would return the following:
Program Help +---------------+-------------+-------------------+ | -h --help | | Help switch. | | -o --output | output_file | Output file name. | | -q --query | query_file | Query file name. | | -v --verbose | | Verbose switch. | +---------------+-------------+-------------------+ Parameter Diagnostics ------------------------- [-h][] [-o][output.txt] [-q][query.sql] [-v][] |
If you didn’t notice, I also took the opportunity to write the help display in such a way that a maintenance programmer could add another switch or parameter easily. This way the programmer only needs to add a new row of text and add an elif statement with the new switch or parameter.
I think using Python’s getopt library is the cleanest and simplest way to implement switch and parameter handling, after all it’s the basis for so many C derived libraries. However, if you must write your own, below is an approach that would work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #!/usr/bin/python # Import libraries. import sys import mysql.connector from mysql.connector import errorcode # ============================================================ # Set local variables for switch and parameter placeholders. # ============================================================ help = False display = \ """ Program Help +---------------+-------------+-------------------+ | -h --help | | Help switch. | | -o --output | output_file | Output file name. | | -q --query | query_file | Query file name. | | -v --verbose | | Verbose switch. | +---------------+-------------+-------------------+""" log = [] output = '' query = '' verbose = False # ============================================================ # Capture argument list minus the program name. # ============================================================ args = sys.argv[1:] # ============================================================ # If one or more args exists and the first one is an # a string that can cast to an int, convert it to an int, # assign it to a variable, and ignore any other args # in the list. # ============================================================ if len(args) > 1 and args[0].isdigit(): powerIn = int(args[0]) # Check for switches and parameters. if isinstance(args,list) and len(args) >= 1: # Set the limit of switches and parameters. argc = len(args) # Enumerate through switches first and then parameters. for i in range(argc): if args[i][0] == '-': # Evaluate switches and ignore any parameter value. if args[i] in ['-h','--help']: help = True # Append entry to log. log.append('[' + str(args[i]) + ']') elif args[i] in ['-v','--verbose']: verbose = True # Append entry to log. log.append('[' + str(args[i]) + ']') # Evaluate parameters. elif i < argc and not args[i+1][0] == '-': if args[i] in ['-q','--query']: query = args[i+1] elif args[i] in ['-o','--output']: output = args[i+1] # Append entry to log. log.append('[' + str(args[i]) + '][' + args[i+1] + ']') else: continue continue # Print the help display when if help: print(display) # Print the parameter handling collected in the log variable. if verbose: for i in log: print(i) |
As you can see from the example, I didn’t give it too much effort. I think it should prove you should use the approach adopted by the general Python community.
SQL Calculations #1
This was principally written for my SQL students but I thought it might be useful to others. SQL calculation are performed row-by-row in the SELECT-list. In its simplest form without even touching a table, you can add two literal numbers like this:
1 | SELECT 2 + 2 AS result; |
It will display the result of the addition to the column alias result as a derived table, or the following result:
+--------+ | result | +--------+ | 4 | +--------+ 1 row in set (0.00 sec) |
Unfortunately, the use of literal values as shown above doesn’t really let you see how the calculation is made row-by-row because it only returns one row. You can rewrite the two literal values into one variable by using a Common Table Expressions (CTEs). The CTE creates an struct tuple with only one x element. Another way to describe what the CTE does would say, it creates a derived table named struct with a single x column in the SELECT-list.
The CTE runs first, then a subsequent query may use the CTE’s derived table results. Below is a query that uses the value in the struct.x derived table (or references the struct tuple’s x element) twice while assigning the value to a new column alias, labelled result. The FROM clause places the struct tuple in the queries namespace, which lets you reference it in the SELECT-list.
1 2 3 4 | WITH struct AS (SELECT 2 AS x) SELECT struct.x + struct.x AS result FROM struct; |
Like the literal example, it will display the result of the addition to the column alias result as a derived table of one row:
+--------+ | result | +--------+ | 4 | +--------+ 1 row in set (0.00 sec) |
Having laid a basis for a simple calculation in one row, let’s expand the example and demonstrate how to perform row-by-row calculations. The example requires introducing some new concepts. One uses the UNION ALL set operator to fabricate a CTE derived table with three rows. Another uses a comma within the WITH clause to create two derived tables or CTEs. The last uses the CROSS JOIN to add the single row CTE’s single y column to each of the rows returned by the multiple row CTE.
The CROSS JOIN is a Cartesian product, which multiplies the rows in one table against the rows in another table while adding the columns from each table. That means fabricating a table of one column and one row lets you put a variable into all the rows of another table or set of tables combined through an equijoin or non-equijoin operation.
The query below takes a struct1 derived table of one column and three rows and a struct2 derived table of one column and one row, then uses a CROSS JOIN to create a new derived table, which would be a table of two columns and three rows. The Cartesian product only provides the two columns that we will multiply to create new data.
The SELECT-list lets us fabricate a new column where we multiply the values of column x and column y to create a set of new results in column result.
1 2 3 4 5 6 7 8 9 10 | WITH struct1 AS (SELECT 1 AS x UNION ALL SELECT 2 AS x UNION ALL SELECT 3 AS x) , struct2 AS (SELECT 10 AS y) SELECT struct1.x AS x , struct2.y AS y , struct1.x * struct2.y AS result FROM struct1 CROSS JOIN struct2; |
The query returns the following results, which show the values used to calculate the result and the result:
+---+----+--------+ | x | y | result | +---+----+--------+ | 1 | 10 | 10 | | 2 | 10 | 20 | | 3 | 10 | 30 | +---+----+--------+ 3 rows in set (0.00 sec) |
As a rule, the columns x and y would not be displayed in the final derived table. You would only see the result columns’ values.
Let’s use an example from Alan Bwaulieu’s Learning SQL book with a twist. Rather than manually fabricating the ordinal numbers twice, let’s use the scope reference of a subsequent CTE to reference an earlier CTE. That would create two ten row tables of one column each, or a Cartesian product of a 100 row table with two columns. Then, let’s use the SELECT-list lets us fabricate only a new column, which will add 1 to the numbers 0 to 99 to give us the numbers 1 to a 100.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | WITH ones AS (SELECT 0 AS x UNION ALL SELECT 1 AS x UNION ALL SELECT 2 AS x UNION ALL SELECT 3 AS x UNION ALL SELECT 4 AS x UNION ALL SELECT 5 AS x UNION ALL SELECT 6 AS x UNION ALL SELECT 7 AS x UNION ALL SELECT 8 AS x UNION ALL SELECT 9 AS x ) , tens AS (SELECT x * 10 AS x FROM ones) SELECT ones.x + tens.x + 1 AS ordinal FROM ones CROSS JOIN tens ORDER BY ordinal; |
It returns the following result set:
+---------+ | ordinal | +---------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | | 11 | ... | 98 | | 99 | | 100 | +---------+ 100 rows in set (0.00 sec) |
Moving on to more complex math, let’s create a numerals table with the result from our prior query. It will enable calculating the factors of exponents. The easiest way to create the table is shown below (only caveat is that it will build it with a biting rather than an int data type).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | CREATE TABLE numerals AS WITH ones AS (SELECT 0 AS x UNION ALL SELECT 1 AS x UNION ALL SELECT 2 AS x UNION ALL SELECT 3 AS x UNION ALL SELECT 4 AS x UNION ALL SELECT 5 AS x UNION ALL SELECT 6 AS x UNION ALL SELECT 7 AS x UNION ALL SELECT 8 AS x UNION ALL SELECT 9 AS x ) , tens AS (SELECT x * 10 AS x FROM ones) SELECT ones.x + tens.x + 1 AS ordinal FROM ones CROSS JOIN tens ORDER BY ordinal; |
Line #15 sets the column alias that determines the name of the column for the numerals table. It can be described after running the foregoing script in MySQL as:
+---------+--------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------+------+-----+---------+-------+ | ordinal | bigint | NO | | 0 | | +---------+--------+------+-----+---------+-------+ 1 row in set (0.00 sec) |
The next query accepts a substitution variable into the WITH clause, which means an external program will call it. (Although, you could use a session level variable, which I would discourage.) This query returns the factors for any given exponent:
1 2 3 4 5 6 7 8 9 | WITH magic AS (SELECT %s AS vkey) SELECT CONCAT(magic.vkey,'^',LOG(magic.vkey,n.ordinal)) AS powers , n.ordinal AS result FROM numerals n CROSS JOIN magic WHERE MOD(n.ordinal,magic.vkey) = 0 AND LOG(magic.vkey,n.ordinal) REGEXP '^[0-9]*$' OR n.ordinal = 1 ORDER BY n.ordinal; |
FYI, in the WHERE clause the regular expression is guarantees only rows returning integer values, and the 1 returns the identity property of an exponent raised to the zero power.
Assuming you created the numerals table, put the foregoing query in a query.sql file (because I was to lazy to write the full parameter handling), and you run it in the same directory as this Python program, it’ll take any valid integer as a value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #!/usr/bin/python # ------------------------------------------------------------ # Name: power.py # Date: 19 Oct 2024 # ------------------------------------------------------------ # Purpose: # ------- # The program shows you how to provide a single agrument # to a query and print the formatted output. # # You can call the program: # # ./power.py 3 # # ------------------------------------------------------------ # Import libraries. import sys import mysql.connector from mysql.connector import errorcode # ============================================================ # Define a local padding function. # ============================================================ def pad(valueIn): # Define local variable. padding = '' # Convert single digit numbers to strings. if isinstance(valueIn,int) and len(str(valueIn)) == 1: padding = ' ' # Return padding space. return padding # ============================================================ # End local function defintion. # ============================================================ # Define any local variables. powerIn = 2 query = "" # ============================================================ # Capture argument list minus the program name. # ============================================================ arguments = sys.argv[1:] # ============================================================ # If one or more arguments exists and the first one is an # a string that can cast to an int, convert it to an int, # assign it to a variable, and ignore any other arguments # in the list. # ============================================================ if len(arguments) >= 1 and arguments[0].isdigit(): powerIn = int(arguments[0]) # ============================================================ # Use a try-catch block to read and parse a query from a # a file found in the same local directory as the Python # program. # ============================================================ try: file = open('query.sql','r') query = file.read().replace('\n',' ').replace(';','') file.close() except IOError: print("Could not read file:", fileName) # ============================================================ # Attempt connection in a try-catch block. # ============================================================ # -------------------------------------------------------- # Open connection, bind variable in query and format # query output before closing the cursor. # -------------------------------------------------------- try: # Open connection. cnx = mysql.connector.connect(user='student', password='student', host='127.0.0.1', database='studentdb') # Create cursor. cursor = cnx.cursor() # Execute cursor, and coerce string to tuple. cursor.execute(query, (powerIn,)) # Display the rows returned by the query. for (powers, result) in cursor: print((" {} is: {}").format(powers, pad(result) + str(result))) # Close cursor. cursor.close() # -------------------------------------------------------- # Handle MySQL exception # -------------------------------------------------------- except mysql.connector.Error as e: if e.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif e.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") else: print("Error code:", e.errno) # error number print("SQLSTATE value:", e.sqlstate) # SQLSTATE value print("Error message:", e.msg) # error message # -------------------------------------------------------- # Close connection after try-catch completes. # -------------------------------------------------------- # Close the connection when the try block completes. else: cnx.close() |
If you forget to call it with a numeric parameter, it uses 2 as the default. You would call it as follows from a Linux prompt from the local directory:
./power.py |
It returns:
2^0 is: 1 2^1 is: 2 2^2 is: 4 2^3 is: 8 2^4 is: 16 2^5 is: 32 2^6 is: 64 |
If you call it with a numeric parameter, it uses the numeric value. You would call it as follows from a Linux prompt from the local directory:
./power.py 3 |
It returns:
3^0 is: 1 3^1 is: 3 3^2 is: 9 3^3 is: 27 3^4 is: 81 |
As always, I hope the post helps folks sort out how and why things work.
SQL Statement Management
It’s very difficult explaining to students new to relational databases how SQL works. There are many parts that seem intuitive and then there are others that confuse and confound.
For beginners, the idea that a SQL statement is simply a text string that you must dispatch to a SQL statement processing engine is new. That’s because they use an Integrated Development Environment (IDE) that hides, or abstracts the complexity, of how SQL executes.
I start my core SQL class by demonstrating how to run a text literal query without a FROM clause in MySQL Workbench, like this:
SELECT 'Hello World!' AS "Output"; |
After writing the query, I highlight everything except the semicolon and click the lightening bolt that dispatches the static string to the SQL statement engine. They see this result:
Then, I launch a mysql Monitor session and write the query with a semicolon to dispatch the SQL static string to the SQL statement engine:
SELECT 'Hello World!' AS "Output"; |
and, with a \g to dispatch the SQL static string to the SQL statement engine:
SELECT 'Hello World!' AS "Output"\g |
Both queries return the same output, as shown below:
+--------------+ | output | +--------------+ | Hello World! | +--------------+ 1 row in set (0.00 sec)
Rewriting the query with a \G to dispatch the SQL static string to the SQL statement engine:
SELECT 'Hello World!' AS "Output"\G |
Both queries return the following output:
*************************** 1. row *************************** output: Hello World! 1 row in set (0.00 sec)
The next step requires removing the MySQL Workbench and MySQL Monitor from the demonstration. Without either of those tools, a Python program can demonstrate how to run a static SQL string.
The query is now a string literal into a query.sql file. The Python program reads the query.sql file, dispatches the embedded query, and displays the query results.
This is the query.sql file is:
SELECT 'Hello World!' AS "output"; |
This is the query.py file is:
#!/usr/bin/python # Import libraries. import sys import mysql.connector from mysql.connector import errorcode # ============================================================ # Use a try-catch block to read and parse a query from a # a file found in the same local directory as the Python # program. # ============================================================ try: file = open('query.sql','r') query = file.read().replace('\n',' ').replace(';','') file.close() except IOError: print("Could not read file:", fileName) # ============================================================ # Attempt connection in a try-catch block. # ============================================================ # -------------------------------------------------------- # Open connection, bind variable in query and format # query output before closing the cursor. # -------------------------------------------------------- try: # Open connection. cnx = mysql.connector.connect(user='student', password='student', host='127.0.0.1', database='studentdb') # Create cursor. cursor = cnx.cursor() # Execute cursor, and coerce string to tuple. cursor.execute(query) # Display the rows returned by the query. for row in cursor: print(row[0]) # Close cursor. cursor.close() # -------------------------------------------------------- # Handle MySQL exception # -------------------------------------------------------- except mysql.connector.Error as e: if e.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif e.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") else: print("Error code:", e.errno) # error number print("SQLSTATE value:", e.sqlstate) # SQLSTATE value print("Error message:", e.msg) # error message # -------------------------------------------------------- # Close connection after try-catch completes. # -------------------------------------------------------- # Close the connection when the try block completes. else: cnx.close() |
In Linux or Unix from the relative directory where both the query.sql and query.py files are located:
./query.py |
It returns:
Hello World!
These examples demonstrate that a query without variable substitution is only a static string. In all the cases, the static SQL strings are dispatched to the SQL engine by a terminator like a semicolon or through an ODBC library call that executes the static SQL string.
Parametric Queries
In 2021, I wrote a MySQL example for my class on the usefulness of Common Table Expressions (CTEs). When discussing the original post, I would comment on how you could extend the last example to build a parametric reporting table.
Somebody finally asked for a concrete example. So, this explains how to build a sample MySQL parametric query by leveraging a filter cross join and tests the parameter use with a Python script.
You can build this in any database you prefer but I used a studentdb database with the sakila sample database installed. I’ve granted privileges to both databases to the student user. The following SQL is required for the example:
-- Conditionally drop the levels table. DROP TABLE IF EXISTS levels; -- Create the levels list. CREATE TABLE levels ( level_id int unsigned primary key auto_increment , parameter_set enum('Three','Five') , description varchar(20) , min_roles int , max_roles int ); -- Insert values into the list table. INSERT INTO levels ( parameter_set , description , min_roles , max_roles ) VALUES ('Three','Hollywood Star', 30, 99999) ,('Three','Prolific Actor', 20, 29) ,('Three','Newcommer',1,19) ,('Five','Newcommer',1,9) ,('Five','Junior Actor',10,19) ,('Five','Professional Actor',20,29) ,('Five','Major Actor',30,39) ,('Five','Hollywood Star',40,99999); |
The sample lets you use the three or five value labels while filtering on any partial full_name value as the result of the query below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | -- Query the data. WITH actors AS (SELECT a.actor_id , a.first_name , a.last_name , COUNT(*) AS num_roles FROM sakila.actor a INNER JOIN sakila.film_actor fa ON a.actor_id = fa.actor_id GROUP BY actor_id) SELECT CONCAT(a.last_name,', ',a.first_name) full_name , l.description , a.num_roles FROM actors a CROSS JOIN levels l WHERE a.num_roles BETWEEN l.min_roles AND l.max_roles AND l.parameter_set = 'Five' AND a.last_name LIKE CONCAT('H','%') ORDER BY a.last_name , a.first_name; |
They extends a concept exercise found in Chapter 9 on subqueries in Alan Beaulieu’s Learning SQL book.
This is the parametric Python program, which embeds the function locally (to make it easier for those who don’t write a lot of Python). You could set the PYTHONPATH to a relative src directory and import your function if you prefer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | #!/usr/bin/python # Import the libraries. import sys import mysql.connector from mysql.connector import errorcode # ============================================================ # Define function to check and replace arguments. def check_replace(argv): # Set defaults for incorrect parameter values. defaults = ("Three","_") # Declare empty list variables. inputs = [] args = () # Check whether or not parameters exist after file name. if isinstance(argv,list) and len(argv) != 0: # Check whether there are at least two parameters. if len(argv) >= 2: # Loop through available command-line arguments. for element in argv: # Check first of two parameter values and substitute # default value if input value is an invalid option. if len(inputs) == 0 and (element in ('Three','Five')) or \ len(inputs) == 1 and (isinstance(element,str)): inputs.append(element) elif len(inputs) == 0: inputs.append(defaults[0]) elif len(inputs) == 1: inputs.append(defaults[1]) # Assign arguments to parameters. args = (inputs) # Check whether only one parameter value exists. elif len(argv) == 1 and (argv[0] in ('Three','Five')): args = (argv[0],"_") # Assume only one parameter is valid and substitute an # empty string as the second parameter. else: args = (defaults[0],"_") # Substitute defaults when missing parameters. else: args = defaults # Return parameters as a tuple. return args # ============================================================ # Assign command-line argument list to variable by removing # the program file name. # ============================================================ params = check_replace(sys.argv[1:]) # ============================================================ # Attempt the query. # ============================================================ # Use a try-catch block to manage the connection. # ============================================================ try: # Open connection. cnx = mysql.connector.connect(user='student', password='student', host='127.0.0.1', database='studentdb') # Create cursor. cursor = cnx.cursor() # Set the query statement. query = ("WITH actors AS " "(SELECT a.first_name " " , a.last_name " " , COUNT(*) AS num_roles " " FROM sakila.actor a INNER JOIN sakila.film_actor fa " " ON a.actor_id = fa.actor_id " " GROUP BY a.first_name " " , a.last_name ) " " SELECT CONCAT(a.last_name,', ',a.first_name) AS full_name " " , l.description " " , a.num_roles " " FROM actors a CROSS JOIN levels l " " WHERE a.num_roles BETWEEN l.min_roles AND l.max_roles " " AND l.parameter_set = %s " " AND a.last_name LIKE CONCAT(%s,'%') " " ORDER BY a.last_name " " , a.first_name") # Execute cursor. cursor.execute(query, params) # Display the rows returned by the query. for (full_name, description, num_roles) in cursor: print('{0} is a {1} with {2} films.'.format( full_name.title() , description.title() , num_roles)) # Close cursor. cursor.close() # ------------------------------------------------------------ # Handle exception and close connection. except mysql.connector.Error as e: if e.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif e.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") else: print("Error code:", e.errno) # error number print("SQLSTATE value:", e.sqlstate) # SQLSTATE value print("Error message:", e.msg) # error message # Close the connection when the try block completes. else: cnx.close() |
As always, I hope this helps those trying to understand how CTEs can solve problems that would otherwise be coded in external imperative languages like Python.
Sqlite on Ubuntu
We decided to include some existing Sqlite databases in our AWS Ubuntu learning lab because they’re used by the Data Science courses (specifically, DS 250). Installing Sqlite is quite simple:
sudo apt install -y sqlite |
You can check the install by using the which utility, like:
which -a sqlite3 |
On Ubuntu, it should return:
/usr/bin/sqlite3 |
There is a friendly help document online that can provide insight in how to use Sqlite. You can create a new student.db database with the following syntax from the Ubuntu CLI (Command-Line Interface):
sqlite3 student.db |
It would return the following:
SQLite version 3.37.2 2022-01-06 13:25:41 Enter ".help" FOR usage hints. sqlite> |
A little warning about the simple example and how it opens only a transient in-memory database. If you want a persistent database, you must open sqlite3 without any arguments. Then, you must use the .open method to open a persistent student.db database create a file in the relative directory path where you launched sqlite3 executable. You can read more about persistent in Sqlite in the documentation.
.open student.db |
The alternative opens the student.db file in a fully qualified path:
.open /home/student/Code/sqlite/db/student.db |
If you type .databases at the sqlite> prompt it would return:
sqlite> .databases main: /home/student/Code/sqlite/db/student.db r/w |
Let’s create a script file that creates two tables, a foreign key reference from one of the tables to the other, and some data with the following create_sample.sql script:
-- Drop knight table if exists. DROP TABLE IF EXISTS knight; -- Drop kingdom table if exists. DROP TABLE IF EXISTS kingdom; -- Create normalized table kingdom CREATE TABLE kingdom ( kingdom_id INTEGER PRIMARY KEY , kingdom_name VARCHAR(20) , population INTEGER , book VARCHAR(40)); -- Insert kingdom into table. INSERT INTO kingdom ( kingdom_id , kingdom_name , population , book ) VALUES ( 1, 'Narnia', 42100, 'Prince Caspian' ) ,( 2, 'Narnia', 77600, 'The Lion, The Witch and The Wardrobe' ) ,( 3, 'Camelot', 15200, 'The Once and Future King' ); -- Create normalized knight table. CREATE TABLE knight ( knight_id INTEGER PRIMARY KEY , knight_name VARCHAR(22) , kingdom_allegiance_id INTEGER , allegiance_start_date text , allegiance_end_date text , book VARCHAR(40) , FOREIGN KEY (kingdom_allegiance_id) REFERENCES kingdom(kingdom_id)); -- Insert knights into table. INSERT INTO knight ( knight_id , knight_name , kingdom_allegiance_id , allegiance_start_date , allegiance_end_date , book ) VALUES ( 1, 'Peter the Magnificent', 2, '1272-03-20', '1292-06-19', 'The Lion, The Witch and The Wardrobe' ) ,( 2, 'Edmund the Just', 2, '1272-03-20', '1292-06-19', 'The Lion, The Witch and The Wardrobe' ) ,( 3, 'Susan the Gentle', 2, '1272-03-20', '1292-06-19', 'The Lion, The Witch and The Wardrobe' ) ,( 4, 'Lucy the Valiant', 2, '1272-03-20', '1292-06-19', 'The Lion, The Witch and The Wardrobe' ) ,( 5, 'Peter the Magnificent', 1, '1531-04-12', '1328-05-31', 'Prince Caspian' ) ,( 6, 'Edmund the Just', 1, '1531-04-12', '1328-05-31', 'Prince Caspian' ) ,( 7, 'Susan the Gentle', 1, '1531-04-12', '1328-05-31', 'Prince Caspian' ) ,( 8, 'Lucy the Valiant', 1, '1531-04-12', '1328-05-31', 'Prince Caspian' ) ,( 9, 'King Arthur', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 10, 'Sir Lionel', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 11, 'Sir Bors', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 12, 'Sir Bors', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 13, 'Sir Galahad', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 14, 'Sir Gawain', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 15, 'Sir Tristram', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 16, 'Sir Percival', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ) ,( 17, 'Sir Lancelot', 3, '0631-03-10', '0686-12-12', 'The Once and Future King' ); |
You can run the create_sample.sql script with the following syntax using an absolute path:
sqlite> .read /home/student/Code/sqlite/create_tables.sql |
Then, you can write a query like this to retrieve the data from two tables:
SELECT k.kingdom_name , kn.knight_name FROM kingdom k INNER JOIN knight kn ON k.kingdom_id = kn.kingdom_allegiance_id WHERE k.book = 'Prince Caspian'; |
It will return the following:
Narnia|Peter the Magnificent Narnia|Edmund the Just Narnia|Susan the Gentle Narnia|Lucy the Valiant |
You can exit sqlite3 by entering .quit or Control+D (the system End-Of-File character). If you can determine whether you have a transient or persistent student.db database file with the long list (ll) command.
The following command:
ll /home/student/Code/sqlite/db/student.db |
should return the following:
-rw-r--r-- 1 student student 12288 Feb 9 23:01 /home/student/Code/sqlite/db/student.db |
If the command returned a 0 sized student.db database file, you created a transient Sqlite table. You’ll need to redo the creation of the student.db database file with the .open command as qualified above.
If you want to detach a database from your active Sqlite session, you can issue the following command to remove it:
sqlite> DETACH DATABASE student.db |
Let’s jazz it up a bit with some Python. The first example verifies the ODBC driver’s ability to connect to Sqlite. Please note that it returns the same result for a transient and persistent database file. You can refer to the following documentation for Python examples.
#!/usr/bin/python # Import sqlite3 ODBC library. import sqlite3 try: # Open a connection to the student.db database db = sqlite3.connect('/home/student/Code/sqlite/db/student.db') # Print a string to say you've connected to the student.db database. print("Sqlite database connection success.") except sqlite3.Error as e: print('SQLite error: %s' % (' '.join(e.args))) print("Exception class is: ", e.__class__) print('SQLite traceback: ') exc_type, exc_value, exc_tb = sys.exc_info() print(traceback.format_exception(exc_type, exc_value, exc_tb)) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
You can run the sqlite_connection.py script with the following syntax from its local directory:
Sqlite database connection success. |
Assuming you have created a persistent Sqlite database, as qualified above with the .open command and fully qualified file name. A fully qualified file name as a path from a Linux mount point to the file.
You must use the fully qualified file name for a persistent Sqlite student.db database as the database parameter for the sqlite3.connect() method, as shown on line #9 of the sqlite_query.py program below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/usr/bin/python # Import sys library. import sqlite3 try: # Open a connection to a persistent database, which should use # a fully qualified file name, but may use a relative file # name when the Python code is in the same directory as a # persistent student.db sqlite3 database. db = sqlite3.connect('/home/student/Code/sqlite/db/student.db') # Create a cursor. cursor = db.cursor() # Define a query. query = "SELECT k.kingdom_name " \ ", kn.knight_name " \ "FROM kingdom k INNER JOIN knight kn " \ "ON k.kingdom_id = kn.kingdom_allegiance_id " \ "WHERE k.book = 'Prince Caspian'" # Execute the cursor with the query. cursor.execute( query ) # Display the rows returned by the query. for (kingdom_name, knight_name) in cursor: print('{0} has {1}'.format( kingdom_name.title(), knight_name.title())) except sqlite3.Error as e: print('SQLite error: %s' % (' '.join(e.args))) print("Exception class is: ", e.__class__) print('SQLite traceback: ') exc_type, exc_value, exc_tb = sys.exc_info() print(traceback.format_exception(exc_type, exc_value, exc_tb)) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
As always, I hope this helps those trying to get up and running with Sqlite.
VSCode & $PYTHONPATH
About 4 years ago, I demonstrated how to develop Python functions with a relative src directory in this old blog post. I thought it might be possible to do with VSCode. Doing a bit of research, it appeared all that was required was adding the PythonPath to VSCode’s Python settings in:
/home/student/.vscode/extensions/ms-python.python-2023.22.0/pythonFiles/.vscode/settings.json |
It contained:
{"files.exclude":{"**/__pycache__/**":true,"**/**/*.pyc":true},"python.formatting.provider":"black"} |
I added a configuration for the PYTHONPATH, as shown:
{"files.exclude":{"**/__pycache__/**":true,"**/**/*.pyc":true},"python.formatting.provider":"black","python.pythonPath": "/home/student/Lib"} |
As you can tell from the embedded VSCode Terminal output below, the PYTHONPATH is not found. You can manually enter it and retest your code successfully. There is no way to use a relative PYTHONPATH like the one you can use from an shell environment file.
This is the hello_whom5.py code:
#!/usr/bin/python # Import the basic sys library. import sys from input import parse_input # Assign command-line argument list to variable. whom = parse_input(sys.argv) # Check if string isn't empty and use dynamic input. if len(whom) > 0: # Print dynamic hello salutation. print("Hello " + whom + "!\n") else: # Print default saluation. print("Hello World!") |
This is the input.py library module:
# Parse a list and return a whitespace delimited string. def parse_input(input_list): # Assign command-line argument list to variable. cmd_list = input_list[1:] # Declare return variable. result = "" # Check whether or not their are parameters beyond the file name. if isinstance(input_list,list) and len(input_list) != 0: # Loop through the command-line argument list and print it. for element in cmd_list: if len(result) == 0: result = element else: result = result + " " + element # Return result variable as string. return result |
This is the Terminal output from VSCode:
student@student-virtual-machine:~$ /bin/python /home/student/Code/python/hello_whom5.py Traceback (most recent call last): File "/home/student/Code/python/hello_whom5.py", line 5, in <module> from input import parse_input ModuleNotFoundError: No module named 'input' student@student-virtual-machine:~$ export set PYTHONPATH=/home/student/Lib student@student-virtual-machine:~$ /bin/python /home/student/Code/python/hello_whom5.py Hello World! student@student-virtual-machine:~$ /bin/python /home/student/Code/python/hello_whom5.py Katniss Everdeen Hello Katniss Everdeen! student@student-virtual-machine:~$ |
The VSCode image for the test follows below:
As always, I hope this helps somebody working the same issue. However, if somebody has a better solution, please let me know.
Oracle 23c Free SQL*Plus
It’s always frustrated me when using the sqlplus command-line interface (CLI) that you can’t just “up arrow” to through the history. At least, that’s the default case unless you wrap the sqlplus executable.
I like to do my development work as close to the database as possible. The delay from SQL Developer to the database or VSCode to the database is just too long. Therefore, I like the native sqlplus to be as efficient as possible. This post shows you how to install the rlwarp utility to wrap sqlplus and create a sandboxed student user for a local development account inside the Oracle 23c Free container. You should note that the Docker or Podman Container is using Oracle Unbreakable Linux 8 as it’s native OS.
You can connect to your Docker version of Oracle Database 23c Free with the following command:
docker exec -it -u root oracle23c bash |
You can’t just use dnf to install rlwrap and get it to magically install all the dependencies. That would be too easy, eh?
Attempting to do so will lock your base OS and eventually force you to kill with prejudice the hung dnf process (at least it forced me to do so). You need to determine the rlwrap dependencies and then install them first. In that process, I noticed that the which utility program wasn’t installed in the container.
Naturally, I installed the which utility first with this command:
dnf install -y which |
Display detailed console log →
Last metadata expiration check: 0:26:00 ago on Thu Dec 21 05:18:09 2023. Dependencies resolved. ================================================================================ Package Architecture Version Repository Size ================================================================================ Installing: which x86_64 2.21-20.el8 ol8_baseos_latest 50 k Transaction Summary ================================================================================ Install 1 Package Total download size: 50 k Installed size: 81 k Downloading Packages: which-2.21-20.el8.x86_64.rpm 80 kB/s | 50 kB 00:00 -------------------------------------------------------------------------------- Total 80 kB/s | 50 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : which-2.21-20.el8.x86_64 1/1 Running scriptlet: which-2.21-20.el8.x86_64 1/1 Verifying : which-2.21-20.el8.x86_64 1/1 Installed: which-2.21-20.el8.x86_64 Complete! |
The rlwrap dependencies are: glibc, ncurses, perl, readline, python, and git. Only the perl, python, and git are missing from the list of formal dependencies but there’s another dependency the epel-release package.
If you want to verify whether a package is installed, you can use the rpm command like this:
rpm -qa | grep package_name |
I installed the perl programming environment (a big install) with this command:
dnf install -y perl |
Display detailed console log →
Last metadata expiration check: 0:28:29 ago on Thu Dec 21 05:18:09 2023. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: perl x86_64 4:5.26.3-422.el8 ol8_appstream 73 k Installing dependencies: dwz x86_64 0.12-10.el8 ol8_appstream 109 k efi-srpm-macros noarch 3-3.0.1.el8 ol8_appstream 22 k file x86_64 5.33-24.el8 ol8_baseos_latest 77 k ghc-srpm-macros noarch 1.4.2-7.el8 ol8_appstream 9.3 k glibc-gconv-extra x86_64 2.28-225.0.3.el8 ol8_baseos_latest 1.5 M go-srpm-macros noarch 2-17.el8 ol8_appstream 13 k groff-base x86_64 1.22.3-18.el8 ol8_baseos_latest 1.0 M ocaml-srpm-macros noarch 5-4.el8 ol8_appstream 9.3 k openblas-srpm-macros noarch 2-2.el8 ol8_appstream 7.9 k perl-Algorithm-Diff noarch 1.1903-9.el8 ol8_baseos_latest 52 k perl-Archive-Tar noarch 2.30-1.el8 ol8_baseos_latest 79 k perl-Archive-Zip noarch 1.60-3.el8 ol8_appstream 108 k perl-Attribute-Handlers noarch 0.99-422.el8 ol8_appstream 89 k perl-B-Debug noarch 1.26-2.el8 ol8_appstream 26 k perl-CPAN noarch 2.18-397.el8 ol8_appstream 554 k perl-CPAN-Meta noarch 2.150010-396.el8 ol8_appstream 191 k perl-CPAN-Meta-Requirements noarch 2.140-396.el8 ol8_appstream 37 k perl-CPAN-Meta-YAML noarch 0.018-397.el8 ol8_appstream 34 k perl-Carp noarch 1.42-396.el8 ol8_baseos_latest 30 k perl-Compress-Bzip2 x86_64 2.26-6.el8 ol8_appstream 72 k perl-Compress-Raw-Bzip2 x86_64 2.081-1.el8 ol8_baseos_latest 40 k perl-Compress-Raw-Zlib x86_64 2.081-1.el8 ol8_baseos_latest 68 k perl-Config-Perl-V noarch 0.30-1.el8 ol8_appstream 22 k perl-DB_File x86_64 1.842-1.el8 ol8_appstream 83 k perl-Data-Dumper x86_64 2.167-399.el8 ol8_baseos_latest 58 k perl-Data-OptList noarch 0.110-6.el8 ol8_appstream 31 k perl-Data-Section noarch 0.200007-3.el8 ol8_appstream 30 k perl-Devel-PPPort x86_64 3.36-5.el8 ol8_appstream 118 k perl-Devel-Peek x86_64 1.26-422.el8 ol8_appstream 94 k perl-Devel-SelfStubber noarch 1.06-422.el8 ol8_appstream 76 k perl-Devel-Size x86_64 0.81-2.el8 ol8_appstream 34 k perl-Digest noarch 1.17-395.el8 ol8_baseos_latest 27 k perl-Digest-MD5 x86_64 2.55-396.el8 ol8_baseos_latest 37 k perl-Digest-SHA x86_64 1:6.02-1.el8 ol8_appstream 66 k perl-Encode x86_64 4:2.97-3.el8 ol8_baseos_latest 1.5 M perl-Encode-devel x86_64 4:2.97-3.el8 ol8_appstream 39 k perl-Env noarch 1.04-395.el8 ol8_appstream 21 k perl-Errno x86_64 1.28-422.el8 ol8_baseos_latest 76 k perl-Exporter noarch 5.72-396.el8 ol8_baseos_latest 34 k perl-ExtUtils-CBuilder noarch 1:0.280230-2.el8 ol8_appstream 48 k perl-ExtUtils-Command noarch 1:7.34-1.el8 ol8_appstream 19 k perl-ExtUtils-Embed noarch 1.34-422.el8 ol8_appstream 79 k perl-ExtUtils-Install noarch 2.14-4.el8 ol8_appstream 46 k perl-ExtUtils-MM-Utils noarch 1:7.34-1.el8 ol8_appstream 16 k perl-ExtUtils-MakeMaker noarch 1:7.34-1.el8 ol8_appstream 300 k perl-ExtUtils-Manifest noarch 1.70-395.el8 ol8_appstream 36 k perl-ExtUtils-Miniperl noarch 1.06-422.el8 ol8_appstream 77 k perl-ExtUtils-ParseXS noarch 1:3.35-2.el8 ol8_appstream 83 k perl-File-Fetch noarch 0.56-2.el8 ol8_appstream 33 k perl-File-HomeDir noarch 1.002-4.el8 ol8_appstream 61 k perl-File-Path noarch 2.15-2.el8 ol8_baseos_latest 38 k perl-File-Temp noarch 0.230.600-1.el8 ol8_baseos_latest 63 k perl-File-Which noarch 1.22-2.el8 ol8_appstream 23 k perl-Filter x86_64 2:1.58-2.el8 ol8_appstream 82 k perl-Filter-Simple noarch 0.94-2.el8 ol8_appstream 29 k perl-Getopt-Long noarch 1:2.50-4.el8 ol8_baseos_latest 63 k perl-HTTP-Tiny noarch 0.074-2.el8 ol8_baseos_latest 57 k perl-IO x86_64 1.38-422.el8 ol8_baseos_latest 142 k perl-IO-Compress noarch 2.081-1.el8 ol8_baseos_latest 258 k perl-IO-Socket-IP noarch 0.39-5.el8 ol8_baseos_latest 47 k perl-IO-Socket-SSL noarch 2.066-4.module+el8.6.0+20623+f0897f98 ol8_appstream 298 k perl-IO-Zlib noarch 1:1.10-422.el8 ol8_baseos_latest 81 k perl-IPC-Cmd noarch 2:1.02-1.el8 ol8_appstream 43 k perl-IPC-SysV x86_64 2.07-397.el8 ol8_appstream 43 k perl-IPC-System-Simple noarch 1.25-17.el8 ol8_appstream 43 k perl-JSON-PP noarch 1:2.97.001-3.el8 ol8_appstream 68 k perl-Locale-Codes noarch 3.57-1.el8 ol8_appstream 310 k perl-Locale-Maketext noarch 1.28-396.el8 ol8_appstream 99 k perl-Locale-Maketext-Simple noarch 1:0.21-422.el8 ol8_appstream 79 k perl-MIME-Base64 x86_64 3.15-396.el8 ol8_baseos_latest 31 k perl-MRO-Compat noarch 0.13-4.el8 ol8_appstream 24 k perl-Math-BigInt noarch 1:1.9998.11-7.el8 ol8_baseos_latest 196 k perl-Math-BigInt-FastCalc x86_64 0.500.600-6.el8 ol8_appstream 27 k perl-Math-BigRat noarch 0.2614-1.el8 ol8_appstream 40 k perl-Math-Complex noarch 1.59-422.el8 ol8_baseos_latest 109 k perl-Memoize noarch 1.03-422.el8 ol8_appstream 119 k perl-Module-Build noarch 2:0.42.24-5.el8 ol8_appstream 273 k perl-Module-CoreList noarch 1:5.20181130-1.el8 ol8_appstream 87 k perl-Module-CoreList-tools noarch 1:5.20181130-1.el8 ol8_appstream 22 k perl-Module-Load noarch 1:0.32-395.el8 ol8_appstream 19 k perl-Module-Load-Conditional noarch 0.68-395.el8 ol8_appstream 24 k perl-Module-Loaded noarch 1:0.08-422.el8 ol8_appstream 75 k perl-Module-Metadata noarch 1.000033-395.el8 ol8_appstream 44 k perl-Mozilla-CA noarch 20160104-7.0.1.module+el8.3.0+21136+b437fca9 ol8_appstream 15 k perl-Net-Ping noarch 2.55-422.el8 ol8_appstream 102 k perl-Net-SSLeay x86_64 1.88-2.module+el8.6.0+20623+f0897f98 ol8_appstream 379 k perl-Package-Generator noarch 1.106-11.el8 ol8_appstream 27 k perl-Params-Check noarch 1:0.38-395.el8 ol8_appstream 24 k perl-Params-Util x86_64 1.07-22.el8 ol8_appstream 44 k perl-PathTools x86_64 3.74-1.el8 ol8_baseos_latest 90 k perl-Perl-OSType noarch 1.010-396.el8 ol8_appstream 29 k perl-PerlIO-via-QuotedPrint noarch 0.08-395.el8 ol8_appstream 13 k perl-Pod-Checker noarch 4:1.73-395.el8 ol8_appstream 33 k perl-Pod-Escapes noarch 1:1.07-395.el8 ol8_baseos_latest 20 k perl-Pod-Html noarch 1.22.02-422.el8 ol8_appstream 88 k perl-Pod-Parser noarch 1.63-396.el8 ol8_appstream 108 k perl-Pod-Perldoc noarch 3.28-396.el8 ol8_baseos_latest 88 k perl-Pod-Simple noarch 1:3.35-395.el8 ol8_baseos_latest 213 k perl-Pod-Usage noarch 4:1.69-395.el8 ol8_baseos_latest 34 k perl-Scalar-List-Utils x86_64 3:1.49-2.el8 ol8_baseos_latest 68 k perl-SelfLoader noarch 1.23-422.el8 ol8_appstream 83 k perl-Socket x86_64 4:2.027-3.el8 ol8_baseos_latest 59 k perl-Software-License noarch 0.103013-2.el8 ol8_appstream 137 k perl-Storable x86_64 1:3.11-3.el8 ol8_baseos_latest 98 k perl-Sub-Exporter noarch 0.987-15.el8 ol8_appstream 73 k perl-Sub-Install noarch 0.928-14.el8 ol8_appstream 27 k perl-Sys-Syslog x86_64 0.35-397.el8 ol8_appstream 50 k perl-Term-ANSIColor noarch 4.06-396.el8 ol8_baseos_latest 46 k perl-Term-Cap noarch 1.17-395.el8 ol8_baseos_latest 23 k perl-Test noarch 1.30-422.el8 ol8_appstream 90 k perl-Test-Harness noarch 1:3.42-1.el8 ol8_appstream 279 k perl-Test-Simple noarch 1:1.302135-1.el8 ol8_appstream 516 k perl-Text-Balanced noarch 2.03-395.el8 ol8_appstream 58 k perl-Text-Diff noarch 1.45-2.el8 ol8_baseos_latest 45 k perl-Text-Glob noarch 0.11-4.el8 ol8_appstream 17 k perl-Text-ParseWords noarch 3.30-395.el8 ol8_baseos_latest 18 k perl-Text-Tabs+Wrap noarch 2013.0523-395.el8 ol8_baseos_latest 24 k perl-Text-Template noarch 1.51-1.el8 ol8_appstream 64 k perl-Thread-Queue noarch 3.13-1.el8 ol8_appstream 24 k perl-Time-HiRes x86_64 4:1.9758-2.el8 ol8_appstream 61 k perl-Time-Local noarch 1:1.280-1.el8 ol8_baseos_latest 33 k perl-Time-Piece x86_64 1.31-422.el8 ol8_appstream 98 k perl-URI noarch 1.73-3.el8 ol8_baseos_latest 116 k perl-Unicode-Collate x86_64 1.25-2.el8 ol8_appstream 686 k perl-Unicode-Normalize x86_64 1.25-396.el8 ol8_baseos_latest 82 k perl-autodie noarch 2.29-396.el8 ol8_appstream 98 k perl-bignum noarch 0.49-2.el8 ol8_appstream 43 k perl-constant noarch 1.33-396.el8 ol8_baseos_latest 25 k perl-devel x86_64 4:5.26.3-422.el8 ol8_appstream 600 k perl-encoding x86_64 4:2.22-3.el8 ol8_appstream 68 k perl-experimental noarch 0.019-2.el8 ol8_appstream 24 k perl-inc-latest noarch 2:0.500-9.el8 ol8_appstream 25 k perl-interpreter x86_64 4:5.26.3-422.el8 ol8_baseos_latest 6.3 M perl-libnet noarch 3.11-3.el8 ol8_baseos_latest 121 k perl-libnetcfg noarch 4:5.26.3-422.el8 ol8_appstream 78 k perl-libs x86_64 4:5.26.3-422.el8 ol8_baseos_latest 1.6 M perl-local-lib noarch 2.000024-2.el8 ol8_appstream 74 k perl-macros x86_64 4:5.26.3-422.el8 ol8_baseos_latest 72 k perl-open noarch 1.11-422.el8 ol8_appstream 78 k perl-parent noarch 1:0.237-1.el8 ol8_baseos_latest 20 k perl-perlfaq noarch 5.20180605-1.el8 ol8_appstream 386 k perl-podlators noarch 4.11-1.el8 ol8_baseos_latest 118 k perl-srpm-macros noarch 1-25.el8 ol8_appstream 11 k perl-threads x86_64 1:2.21-2.el8 ol8_baseos_latest 61 k perl-threads-shared x86_64 1.58-2.el8 ol8_baseos_latest 48 k perl-utils noarch 5.26.3-422.el8 ol8_appstream 129 k perl-version x86_64 6:0.99.24-1.el8 ol8_appstream 67 k python-rpm-macros noarch 3-45.el8 ol8_appstream 16 k python-srpm-macros noarch 3-45.el8 ol8_appstream 16 k python3-pyparsing noarch 2.1.10-7.el8 ol8_baseos_latest 142 k python3-rpm-macros noarch 3-45.el8 ol8_appstream 15 k qt5-srpm-macros noarch 5.15.3-1.el8 ol8_appstream 11 k redhat-rpm-config noarch 131-1.0.1.el8 ol8_appstream 91 k rust-srpm-macros noarch 5-2.el8 ol8_appstream 9.2 k systemtap-sdt-devel x86_64 4.9-3.0.1.el8 ol8_appstream 88 k zip x86_64 3.0-23.el8 ol8_baseos_latest 270 k Installing weak dependencies: perl-Encode-Locale noarch 1.05-10.module+el8.3.0+7692+542c56f9 ol8_appstream 22 k perl-TermReadKey x86_64 2.37-7.el8 ol8_appstream 40 k Enabling module streams: perl 5.26 perl-IO-Socket-SSL 2.066 perl-libwww-perl 6.34 Transaction Summary ================================================================================ Install 159 Packages Total download size: 25 M Installed size: 73 M Downloading Packages: (1/159): file-5.33-24.el8.x86_64.rpm 163 kB/s | 77 kB 00:00 (2/159): perl-Algorithm-Diff-1.1903-9.el8.noarc 531 kB/s | 52 kB 00:00 (3/159): groff-base-1.22.3-18.el8.x86_64.rpm 1.5 MB/s | 1.0 MB 00:00 (4/159): perl-Archive-Tar-2.30-1.el8.noarch.rpm 642 kB/s | 79 kB 00:00 (5/159): perl-Carp-1.42-396.el8.noarch.rpm 449 kB/s | 30 kB 00:00 (6/159): perl-Compress-Raw-Bzip2-2.081-1.el8.x8 452 kB/s | 40 kB 00:00 (7/159): perl-Compress-Raw-Zlib-2.081-1.el8.x86 968 kB/s | 68 kB 00:00 (8/159): perl-Data-Dumper-2.167-399.el8.x86_64. 734 kB/s | 58 kB 00:00 (9/159): perl-Digest-1.17-395.el8.noarch.rpm 391 kB/s | 27 kB 00:00 (10/159): perl-Digest-MD5-2.55-396.el8.x86_64.r 481 kB/s | 37 kB 00:00 (11/159): perl-Errno-1.28-422.el8.x86_64.rpm 811 kB/s | 76 kB 00:00 (12/159): perl-Encode-2.97-3.el8.x86_64.rpm 9.4 MB/s | 1.5 MB 00:00 (13/159): perl-File-Path-2.15-2.el8.noarch.rpm 627 kB/s | 38 kB 00:00 (14/159): perl-Exporter-5.72-396.el8.noarch.rpm 466 kB/s | 34 kB 00:00 (15/159): perl-Getopt-Long-2.50-4.el8.noarch.rp 867 kB/s | 63 kB 00:00 (16/159): perl-File-Temp-0.230.600-1.el8.noarch 648 kB/s | 63 kB 00:00 (17/159): perl-HTTP-Tiny-0.074-2.el8.noarch.rpm 847 kB/s | 57 kB 00:00 (18/159): perl-IO-Compress-2.081-1.el8.noarch.r 3.5 MB/s | 258 kB 00:00 (19/159): perl-IO-1.38-422.el8.x86_64.rpm 1.2 MB/s | 142 kB 00:00 (20/159): perl-IO-Socket-IP-0.39-5.el8.noarch.r 614 kB/s | 47 kB 00:00 (21/159): perl-IO-Zlib-1.10-422.el8.noarch.rpm 881 kB/s | 81 kB 00:00 (22/159): perl-MIME-Base64-3.15-396.el8.x86_64. 425 kB/s | 31 kB 00:00 (23/159): perl-Math-BigInt-1.9998.11-7.el8.noar 1.5 MB/s | 196 kB 00:00 (24/159): perl-Math-Complex-1.59-422.el8.noarch 1.5 MB/s | 109 kB 00:00 (25/159): perl-Pod-Escapes-1.07-395.el8.noarch. 300 kB/s | 20 kB 00:00 (26/159): perl-PathTools-3.74-1.el8.x86_64.rpm 1.2 MB/s | 90 kB 00:00 (27/159): perl-Pod-Perldoc-3.28-396.el8.noarch. 1.2 MB/s | 88 kB 00:00 (28/159): perl-Pod-Simple-3.35-395.el8.noarch.r 2.2 MB/s | 213 kB 00:00 (29/159): perl-Pod-Usage-1.69-395.el8.noarch.rp 499 kB/s | 34 kB 00:00 (30/159): perl-Scalar-List-Utils-1.49-2.el8.x86 947 kB/s | 68 kB 00:00 (31/159): perl-Socket-2.027-3.el8.x86_64.rpm 864 kB/s | 59 kB 00:00 (32/159): perl-Storable-3.11-3.el8.x86_64.rpm 1.2 MB/s | 98 kB 00:00 (33/159): perl-Term-ANSIColor-4.06-396.el8.noar 677 kB/s | 46 kB 00:00 (34/159): perl-Term-Cap-1.17-395.el8.noarch.rpm 321 kB/s | 23 kB 00:00 (35/159): perl-Text-Diff-1.45-2.el8.noarch.rpm 596 kB/s | 45 kB 00:00 (36/159): perl-Text-ParseWords-3.30-395.el8.noa 257 kB/s | 18 kB 00:00 (37/159): perl-Text-Tabs+Wrap-2013.0523-395.el8 351 kB/s | 24 kB 00:00 (38/159): perl-Time-Local-1.280-1.el8.noarch.rp 440 kB/s | 33 kB 00:00 (39/159): perl-URI-1.73-3.el8.noarch.rpm 1.6 MB/s | 116 kB 00:00 (40/159): perl-Unicode-Normalize-1.25-396.el8.x 1.1 MB/s | 82 kB 00:00 (41/159): perl-constant-1.33-396.el8.noarch.rpm 395 kB/s | 25 kB 00:00 (42/159): perl-libnet-3.11-3.el8.noarch.rpm 1.8 MB/s | 121 kB 00:00 (43/159): perl-libs-5.26.3-422.el8.x86_64.rpm 13 MB/s | 1.6 MB 00:00 (44/159): perl-macros-5.26.3-422.el8.x86_64.rpm 1.1 MB/s | 72 kB 00:00 (45/159): perl-parent-0.237-1.el8.noarch.rpm 279 kB/s | 20 kB 00:00 (46/159): perl-podlators-4.11-1.el8.noarch.rpm 1.3 MB/s | 118 kB 00:00 (47/159): perl-interpreter-5.26.3-422.el8.x86_6 14 MB/s | 6.3 MB 00:00 (48/159): glibc-gconv-extra-2.28-225.0.3.el8.x8 601 kB/s | 1.5 MB 00:02 (49/159): perl-threads-2.21-2.el8.x86_64.rpm 876 kB/s | 61 kB 00:00 (50/159): perl-threads-shared-1.58-2.el8.x86_64 657 kB/s | 48 kB 00:00 (51/159): python3-pyparsing-2.1.10-7.el8.noarch 2.0 MB/s | 142 kB 00:00 (52/159): zip-3.0-23.el8.x86_64.rpm 3.7 MB/s | 270 kB 00:00 (53/159): dwz-0.12-10.el8.x86_64.rpm 1.6 MB/s | 109 kB 00:00 (54/159): efi-srpm-macros-3-3.0.1.el8.noarch.rp 350 kB/s | 22 kB 00:00 (55/159): ghc-srpm-macros-1.4.2-7.el8.noarch.rp 125 kB/s | 9.3 kB 00:00 (56/159): go-srpm-macros-2-17.el8.noarch.rpm 198 kB/s | 13 kB 00:00 (57/159): ocaml-srpm-macros-5-4.el8.noarch.rpm 154 kB/s | 9.3 kB 00:00 (58/159): openblas-srpm-macros-2-2.el8.noarch.r 116 kB/s | 7.9 kB 00:00 (59/159): perl-5.26.3-422.el8.x86_64.rpm 921 kB/s | 73 kB 00:00 (60/159): perl-Archive-Zip-1.60-3.el8.noarch.rp 1.4 MB/s | 108 kB 00:00 (61/159): perl-Attribute-Handlers-0.99-422.el8. 1.2 MB/s | 89 kB 00:00 (62/159): perl-B-Debug-1.26-2.el8.noarch.rpm 356 kB/s | 26 kB 00:00 (63/159): perl-CPAN-2.18-397.el8.noarch.rpm 5.3 MB/s | 554 kB 00:00 (64/159): perl-CPAN-Meta-2.150010-396.el8.noarc 2.3 MB/s | 191 kB 00:00 (65/159): perl-CPAN-Meta-Requirements-2.140-396 512 kB/s | 37 kB 00:00 (66/159): perl-CPAN-Meta-YAML-0.018-397.el8.noa 508 kB/s | 34 kB 00:00 (67/159): perl-Compress-Bzip2-2.26-6.el8.x86_64 990 kB/s | 72 kB 00:00 (68/159): perl-Config-Perl-V-0.30-1.el8.noarch. 337 kB/s | 22 kB 00:00 (69/159): perl-DB_File-1.842-1.el8.x86_64.rpm 1.2 MB/s | 83 kB 00:00 (70/159): perl-Data-OptList-0.110-6.el8.noarch. 457 kB/s | 31 kB 00:00 (71/159): perl-Data-Section-0.200007-3.el8.noar 423 kB/s | 30 kB 00:00 (72/159): perl-Devel-PPPort-3.36-5.el8.x86_64.r 1.6 MB/s | 118 kB 00:00 (73/159): perl-Devel-Peek-1.26-422.el8.x86_64.r 960 kB/s | 94 kB 00:00 (74/159): perl-Devel-SelfStubber-1.06-422.el8.n 831 kB/s | 76 kB 00:00 (75/159): perl-Devel-Size-0.81-2.el8.x86_64.rpm 510 kB/s | 34 kB 00:00 (76/159): perl-Digest-SHA-6.02-1.el8.x86_64.rpm 859 kB/s | 66 kB 00:00 (77/159): perl-Encode-Locale-1.05-10.module+el8 285 kB/s | 22 kB 00:00 (78/159): perl-Encode-devel-2.97-3.el8.x86_64.r 510 kB/s | 39 kB 00:00 (79/159): perl-Env-1.04-395.el8.noarch.rpm 321 kB/s | 21 kB 00:00 (80/159): perl-ExtUtils-CBuilder-0.280230-2.el8 730 kB/s | 48 kB 00:00 (81/159): perl-ExtUtils-Command-7.34-1.el8.noar 248 kB/s | 19 kB 00:00 (82/159): perl-ExtUtils-Embed-1.34-422.el8.noar 1.1 MB/s | 79 kB 00:00 (83/159): perl-ExtUtils-Install-2.14-4.el8.noar 661 kB/s | 46 kB 00:00 (84/159): perl-ExtUtils-MM-Utils-7.34-1.el8.noa 243 kB/s | 16 kB 00:00 (85/159): perl-ExtUtils-MakeMaker-7.34-1.el8.no 4.0 MB/s | 300 kB 00:00 (86/159): perl-ExtUtils-Manifest-1.70-395.el8.n 500 kB/s | 36 kB 00:00 (87/159): perl-ExtUtils-Miniperl-1.06-422.el8.n 1.1 MB/s | 77 kB 00:00 (88/159): perl-File-HomeDir-1.002-4.el8.noarch. 980 kB/s | 61 kB 00:00 (89/159): perl-File-Fetch-0.56-2.el8.noarch.rpm 483 kB/s | 33 kB 00:00 (90/159): perl-ExtUtils-ParseXS-3.35-2.el8.noar 1.1 MB/s | 83 kB 00:00 (91/159): perl-Filter-Simple-0.94-2.el8.noarch. 417 kB/s | 29 kB 00:00 (92/159): perl-File-Which-1.22-2.el8.noarch.rpm 312 kB/s | 23 kB 00:00 (93/159): perl-Filter-1.58-2.el8.x86_64.rpm 1.1 MB/s | 82 kB 00:00 (94/159): perl-IO-Socket-SSL-2.066-4.module+el8 3.6 MB/s | 298 kB 00:00 (95/159): perl-IPC-Cmd-1.02-1.el8.noarch.rpm 545 kB/s | 43 kB 00:00 (96/159): perl-IPC-SysV-2.07-397.el8.x86_64.rpm 544 kB/s | 43 kB 00:00 (97/159): perl-IPC-System-Simple-1.25-17.el8.no 535 kB/s | 43 kB 00:00 (98/159): perl-JSON-PP-2.97.001-3.el8.noarch.rp 853 kB/s | 68 kB 00:00 (99/159): perl-Locale-Codes-3.57-1.el8.noarch.r 3.7 MB/s | 310 kB 00:00 (100/159): perl-MRO-Compat-0.13-4.el8.noarch.rp 399 kB/s | 24 kB 00:00 (101/159): perl-Locale-Maketext-1.28-396.el8.no 1.4 MB/s | 99 kB 00:00 (102/159): perl-Locale-Maketext-Simple-0.21-422 1.1 MB/s | 79 kB 00:00 (103/159): perl-Math-BigInt-FastCalc-0.500.600- 371 kB/s | 27 kB 00:00 (104/159): perl-Math-BigRat-0.2614-1.el8.noarch 560 kB/s | 40 kB 00:00 (105/159): perl-Memoize-1.03-422.el8.noarch.rpm 1.6 MB/s | 119 kB 00:00 (106/159): perl-Module-Build-0.42.24-5.el8.noar 3.4 MB/s | 273 kB 00:00 (107/159): perl-Module-CoreList-tools-5.2018113 297 kB/s | 22 kB 00:00 (108/159): perl-Module-CoreList-5.20181130-1.el 1.1 MB/s | 87 kB 00:00 (109/159): perl-Module-Load-0.32-395.el8.noarch 242 kB/s | 19 kB 00:00 (110/159): perl-Module-Load-Conditional-0.68-39 316 kB/s | 24 kB 00:00 (111/159): perl-Module-Loaded-0.08-422.el8.noar 972 kB/s | 75 kB 00:00 (112/159): perl-Module-Metadata-1.000033-395.el 664 kB/s | 44 kB 00:00 (113/159): perl-Mozilla-CA-20160104-7.0.1.modul 229 kB/s | 15 kB 00:00 (114/159): perl-Net-Ping-2.55-422.el8.noarch.rp 1.5 MB/s | 102 kB 00:00 (115/159): perl-Package-Generator-1.106-11.el8. 386 kB/s | 27 kB 00:00 (116/159): perl-Params-Check-0.38-395.el8.noarc 333 kB/s | 24 kB 00:00 (117/159): perl-Net-SSLeay-1.88-2.module+el8.6. 4.4 MB/s | 379 kB 00:00 (118/159): perl-Perl-OSType-1.010-396.el8.noarc 459 kB/s | 29 kB 00:00 (119/159): perl-Params-Util-1.07-22.el8.x86_64. 656 kB/s | 44 kB 00:00 (120/159): perl-PerlIO-via-QuotedPrint-0.08-395 206 kB/s | 13 kB 00:00 (121/159): perl-Pod-Checker-1.73-395.el8.noarch 449 kB/s | 33 kB 00:00 (122/159): perl-Pod-Parser-1.63-396.el8.noarch. 1.6 MB/s | 108 kB 00:00 (123/159): perl-Pod-Html-1.22.02-422.el8.noarch 1.1 MB/s | 88 kB 00:00 (124/159): perl-SelfLoader-1.23-422.el8.noarch. 1.1 MB/s | 83 kB 00:00 (125/159): perl-Software-License-0.103013-2.el8 1.8 MB/s | 137 kB 00:00 (126/159): perl-Sub-Exporter-0.987-15.el8.noarc 1.0 MB/s | 73 kB 00:00 (127/159): perl-Sub-Install-0.928-14.el8.noarch 383 kB/s | 27 kB 00:00 (128/159): perl-Sys-Syslog-0.35-397.el8.x86_64. 734 kB/s | 50 kB 00:00 (129/159): perl-TermReadKey-2.37-7.el8.x86_64.r 536 kB/s | 40 kB 00:00 (130/159): perl-Test-1.30-422.el8.noarch.rpm 1.2 MB/s | 90 kB 00:00 (131/159): perl-Test-Harness-3.42-1.el8.noarch. 3.4 MB/s | 279 kB 00:00 (132/159): perl-Test-Simple-1.302135-1.el8.noar 5.2 MB/s | 516 kB 00:00 (133/159): perl-Text-Glob-0.11-4.el8.noarch.rpm 272 kB/s | 17 kB 00:00 (134/159): perl-Text-Balanced-2.03-395.el8.noar 807 kB/s | 58 kB 00:00 (135/159): perl-Text-Template-1.51-1.el8.noarch 841 kB/s | 64 kB 00:00 (136/159): perl-Time-HiRes-1.9758-2.el8.x86_64. 855 kB/s | 61 kB 00:00 (137/159): perl-Thread-Queue-3.13-1.el8.noarch. 319 kB/s | 24 kB 00:00 (138/159): perl-Time-Piece-1.31-422.el8.x86_64. 1.3 MB/s | 98 kB 00:00 (139/159): perl-autodie-2.29-396.el8.noarch.rpm 1.3 MB/s | 98 kB 00:00 (140/159): perl-Unicode-Collate-1.25-2.el8.x86_ 7.2 MB/s | 686 kB 00:00 (141/159): perl-bignum-0.49-2.el8.noarch.rpm 620 kB/s | 43 kB 00:00 (142/159): perl-encoding-2.22-3.el8.x86_64.rpm 934 kB/s | 68 kB 00:00 (143/159): perl-devel-5.26.3-422.el8.x86_64.rpm 6.5 MB/s | 600 kB 00:00 (144/159): perl-experimental-0.019-2.el8.noarch 327 kB/s | 24 kB 00:00 (145/159): perl-inc-latest-0.500-9.el8.noarch.r 331 kB/s | 25 kB 00:00 (146/159): perl-libnetcfg-5.26.3-422.el8.noarch 1.0 MB/s | 78 kB 00:00 (147/159): perl-local-lib-2.000024-2.el8.noarch 1.1 MB/s | 74 kB 00:00 (148/159): perl-srpm-macros-1-25.el8.noarch.rpm 157 kB/s | 11 kB 00:00 (149/159): perl-open-1.11-422.el8.noarch.rpm 1.0 MB/s | 78 kB 00:00 (150/159): perl-perlfaq-5.20180605-1.el8.noarch 4.7 MB/s | 386 kB 00:00 (151/159): perl-version-0.99.24-1.el8.x86_64.rp 1.0 MB/s | 67 kB 00:00 (152/159): perl-utils-5.26.3-422.el8.noarch.rpm 1.7 MB/s | 129 kB 00:00 (153/159): python-rpm-macros-3-45.el8.noarch.rp 219 kB/s | 16 kB 00:00 (154/159): python3-rpm-macros-3-45.el8.noarch.r 243 kB/s | 15 kB 00:00 (155/159): python-srpm-macros-3-45.el8.noarch.r 239 kB/s | 16 kB 00:00 (156/159): qt5-srpm-macros-5.15.3-1.el8.noarch. 132 kB/s | 11 kB 00:00 (157/159): rust-srpm-macros-5-2.el8.noarch.rpm 128 kB/s | 9.2 kB 00:00 (158/159): redhat-rpm-config-131-1.0.1.el8.noar 1.2 MB/s | 91 kB 00:00 (159/159): systemtap-sdt-devel-4.9-3.0.1.el8.x8 1.2 MB/s | 88 kB 00:00 -------------------------------------------------------------------------------- Total 4.6 MB/s | 25 MB 00:05 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : python-srpm-macros-3-45.el8.noarch 1/159 Installing : python-rpm-macros-3-45.el8.noarch 2/159 Installing : python3-rpm-macros-3-45.el8.noarch 3/159 Installing : rust-srpm-macros-5-2.el8.noarch 4/159 Installing : qt5-srpm-macros-5.15.3-1.el8.noarch 5/159 Installing : perl-srpm-macros-1-25.el8.noarch 6/159 Installing : openblas-srpm-macros-2-2.el8.noarch 7/159 Installing : ocaml-srpm-macros-5-4.el8.noarch 8/159 Installing : go-srpm-macros-2-17.el8.noarch 9/159 Installing : ghc-srpm-macros-1.4.2-7.el8.noarch 10/159 Installing : efi-srpm-macros-3-3.0.1.el8.noarch 11/159 Installing : dwz-0.12-10.el8.x86_64 12/159 Installing : zip-3.0-23.el8.x86_64 13/159 Installing : python3-pyparsing-2.1.10-7.el8.noarch 14/159 Installing : systemtap-sdt-devel-4.9-3.0.1.el8.x86_64 15/159 Installing : groff-base-1.22.3-18.el8.x86_64 16/159 Installing : perl-Digest-1.17-395.el8.noarch 17/159 Installing : perl-Digest-MD5-2.55-396.el8.x86_64 18/159 Installing : perl-Data-Dumper-2.167-399.el8.x86_64 19/159 Installing : perl-libnet-3.11-3.el8.noarch 20/159 Installing : perl-URI-1.73-3.el8.noarch 21/159 Installing : perl-Pod-Escapes-1:1.07-395.el8.noarch 22/159 Installing : perl-IO-Socket-IP-0.39-5.el8.noarch 23/159 Installing : perl-Time-Local-1:1.280-1.el8.noarch 24/159 Installing : perl-Mozilla-CA-20160104-7.0.1.module+el8.3.0+21 25/159 Installing : perl-IO-Socket-SSL-2.066-4.module+el8.6.0+20623+ 26/159 Installing : perl-Net-SSLeay-1.88-2.module+el8.6.0+20623+f089 27/159 Installing : perl-Term-ANSIColor-4.06-396.el8.noarch 28/159 Installing : perl-Term-Cap-1.17-395.el8.noarch 29/159 Installing : perl-File-Temp-0.230.600-1.el8.noarch 30/159 Installing : perl-HTTP-Tiny-0.074-2.el8.noarch 31/159 Installing : perl-Pod-Simple-1:3.35-395.el8.noarch 32/159 Installing : perl-podlators-4.11-1.el8.noarch 33/159 Installing : perl-Pod-Perldoc-3.28-396.el8.noarch 34/159 Installing : perl-Text-ParseWords-3.30-395.el8.noarch 35/159 Installing : perl-Pod-Usage-4:1.69-395.el8.noarch 36/159 Installing : perl-MIME-Base64-3.15-396.el8.x86_64 37/159 Installing : perl-Storable-1:3.11-3.el8.x86_64 38/159 Installing : perl-Getopt-Long-1:2.50-4.el8.noarch 39/159 Installing : perl-Errno-1.28-422.el8.x86_64 40/159 Installing : perl-Socket-4:2.027-3.el8.x86_64 41/159 Installing : perl-Encode-4:2.97-3.el8.x86_64 42/159 Installing : perl-Carp-1.42-396.el8.noarch 43/159 Installing : perl-Exporter-5.72-396.el8.noarch 44/159 Installing : perl-libs-4:5.26.3-422.el8.x86_64 45/159 Installing : perl-Scalar-List-Utils-3:1.49-2.el8.x86_64 46/159 Installing : perl-parent-1:0.237-1.el8.noarch 47/159 Installing : perl-macros-4:5.26.3-422.el8.x86_64 48/159 Installing : perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch 49/159 Installing : perl-Unicode-Normalize-1.25-396.el8.x86_64 50/159 Installing : perl-File-Path-2.15-2.el8.noarch 51/159 Installing : perl-IO-1.38-422.el8.x86_64 52/159 Installing : perl-PathTools-3.74-1.el8.x86_64 53/159 Installing : perl-constant-1.33-396.el8.noarch 54/159 Installing : perl-threads-1:2.21-2.el8.x86_64 55/159 Installing : perl-threads-shared-1.58-2.el8.x86_64 56/159 Installing : perl-interpreter-4:5.26.3-422.el8.x86_64 57/159 Installing : perl-version-6:0.99.24-1.el8.x86_64 58/159 Installing : perl-Time-HiRes-4:1.9758-2.el8.x86_64 59/159 Installing : perl-CPAN-Meta-Requirements-2.140-396.el8.noarch 60/159 Installing : perl-ExtUtils-Manifest-1.70-395.el8.noarch 61/159 Installing : perl-ExtUtils-ParseXS-1:3.35-2.el8.noarch 62/159 Installing : perl-Test-Harness-1:3.42-1.el8.noarch 63/159 Installing : perl-Module-CoreList-1:5.20181130-1.el8.noarch 64/159 Installing : perl-Module-Metadata-1.000033-395.el8.noarch 65/159 Installing : perl-Compress-Raw-Zlib-2.081-1.el8.x86_64 66/159 Installing : perl-Filter-2:1.58-2.el8.x86_64 67/159 Installing : perl-SelfLoader-1.23-422.el8.noarch 68/159 Installing : perl-Module-Load-1:0.32-395.el8.noarch 69/159 Installing : perl-Perl-OSType-1.010-396.el8.noarch 70/159 Installing : perl-Text-Balanced-2.03-395.el8.noarch 71/159 Installing : perl-encoding-4:2.22-3.el8.x86_64 72/159 Installing : perl-Net-Ping-2.55-422.el8.noarch 73/159 Installing : perl-Compress-Raw-Bzip2-2.081-1.el8.x86_64 74/159 Installing : perl-IO-Compress-2.081-1.el8.noarch 75/159 Installing : perl-IO-Zlib-1:1.10-422.el8.noarch 76/159 Installing : perl-Math-Complex-1.59-422.el8.noarch 77/159 Installing : perl-Math-BigInt-1:1.9998.11-7.el8.noarch 78/159 Installing : perl-JSON-PP-1:2.97.001-3.el8.noarch 79/159 Installing : perl-Math-BigRat-0.2614-1.el8.noarch 80/159 Installing : perl-CPAN-Meta-YAML-0.018-397.el8.noarch 81/159 Installing : perl-CPAN-Meta-2.150010-396.el8.noarch 82/159 Installing : perl-Digest-SHA-1:6.02-1.el8.x86_64 83/159 Installing : perl-ExtUtils-Command-1:7.34-1.el8.noarch 84/159 Installing : perl-Locale-Maketext-1.28-396.el8.noarch 85/159 Installing : perl-Locale-Maketext-Simple-1:0.21-422.el8.noarc 86/159 Installing : perl-Params-Check-1:0.38-395.el8.noarch 87/159 Installing : perl-Module-Load-Conditional-0.68-395.el8.noarch 88/159 Installing : perl-Params-Util-1.07-22.el8.x86_64 89/159 Installing : perl-Pod-Html-1.22.02-422.el8.noarch 90/159 Installing : perl-Sub-Install-0.928-14.el8.noarch 91/159 Installing : perl-Data-OptList-0.110-6.el8.noarch 92/159 Installing : perl-bignum-0.49-2.el8.noarch 93/159 Installing : perl-Math-BigInt-FastCalc-0.500.600-6.el8.x86_64 94/159 Installing : perl-open-1.11-422.el8.noarch 95/159 Installing : perl-Filter-Simple-0.94-2.el8.noarch 96/159 Installing : perl-Devel-SelfStubber-1.06-422.el8.noarch 97/159 Installing : perl-Archive-Zip-1.60-3.el8.noarch 98/159 Installing : perl-Module-CoreList-tools-1:5.20181130-1.el8.no 99/159 Installing : perl-experimental-0.019-2.el8.noarch 100/159 Installing : perl-Algorithm-Diff-1.1903-9.el8.noarch 101/159 Installing : perl-Text-Diff-1.45-2.el8.noarch 102/159 Installing : perl-Archive-Tar-2.30-1.el8.noarch 103/159 Installing : perl-Attribute-Handlers-0.99-422.el8.noarch 104/159 Installing : perl-B-Debug-1.26-2.el8.noarch 105/159 Installing : perl-Compress-Bzip2-2.26-6.el8.x86_64 106/159 Installing : perl-Config-Perl-V-0.30-1.el8.noarch 107/159 Installing : perl-DB_File-1.842-1.el8.x86_64 108/159 Installing : perl-Devel-PPPort-3.36-5.el8.x86_64 109/159 Installing : perl-Devel-Size-0.81-2.el8.x86_64 110/159 Installing : perl-Encode-Locale-1.05-10.module+el8.3.0+7692+5 111/159 Installing : perl-Env-1.04-395.el8.noarch 112/159 Installing : perl-ExtUtils-MM-Utils-1:7.34-1.el8.noarch 113/159 Installing : perl-IPC-Cmd-2:1.02-1.el8.noarch 114/159 Installing : perl-File-Fetch-0.56-2.el8.noarch 115/159 Installing : perl-IPC-SysV-2.07-397.el8.x86_64 116/159 Installing : perl-IPC-System-Simple-1.25-17.el8.noarch 117/159 Installing : perl-autodie-2.29-396.el8.noarch 118/159 Installing : perl-Locale-Codes-3.57-1.el8.noarch 119/159 Installing : perl-Memoize-1.03-422.el8.noarch 120/159 Installing : perl-Module-Loaded-1:0.08-422.el8.noarch 121/159 Installing : perl-Package-Generator-1.106-11.el8.noarch 122/159 Installing : perl-Sub-Exporter-0.987-15.el8.noarch 123/159 Installing : perl-Pod-Checker-4:1.73-395.el8.noarch 124/159 Installing : perl-Pod-Parser-1.63-396.el8.noarch 125/159 Installing : perl-Sys-Syslog-0.35-397.el8.x86_64 126/159 Installing : perl-TermReadKey-2.37-7.el8.x86_64 127/159 Installing : perl-Test-1.30-422.el8.noarch 128/159 Installing : perl-Test-Simple-1:1.302135-1.el8.noarch 129/159 Installing : perl-Text-Glob-0.11-4.el8.noarch 130/159 Installing : perl-Text-Template-1.51-1.el8.noarch 131/159 Installing : perl-Time-Piece-1.31-422.el8.x86_64 132/159 Installing : perl-Unicode-Collate-1.25-2.el8.x86_64 133/159 Installing : perl-local-lib-2.000024-2.el8.noarch 134/159 Installing : perl-utils-5.26.3-422.el8.noarch 135/159 Installing : perl-Thread-Queue-3.13-1.el8.noarch 136/159 Installing : perl-File-Which-1.22-2.el8.noarch 137/159 Installing : perl-File-HomeDir-1.002-4.el8.noarch 138/159 Installing : perl-Devel-Peek-1.26-422.el8.x86_64 139/159 Installing : perl-MRO-Compat-0.13-4.el8.noarch 140/159 Installing : perl-Data-Section-0.200007-3.el8.noarch 141/159 Installing : perl-Software-License-0.103013-2.el8.noarch 142/159 Installing : perl-PerlIO-via-QuotedPrint-0.08-395.el8.noarch 143/159 Installing : perl-perlfaq-5.20180605-1.el8.noarch 144/159 Installing : glibc-gconv-extra-2.28-225.0.3.el8.x86_64 145/159 Running scriptlet: glibc-gconv-extra-2.28-225.0.3.el8.x86_64 145/159 Installing : file-5.33-24.el8.x86_64 146/159 Installing : redhat-rpm-config-131-1.0.1.el8.noarch 147/159 Installing : perl-ExtUtils-Install-2.14-4.el8.noarch 148/159 Installing : perl-devel-4:5.26.3-422.el8.x86_64 149/159 Installing : perl-ExtUtils-MakeMaker-1:7.34-1.el8.noarch 150/159 Installing : perl-ExtUtils-CBuilder-1:0.280230-2.el8.noarch 151/159 Installing : perl-ExtUtils-Embed-1.34-422.el8.noarch 152/159 Installing : perl-ExtUtils-Miniperl-1.06-422.el8.noarch 153/159 Installing : perl-libnetcfg-4:5.26.3-422.el8.noarch 154/159 Installing : perl-Encode-devel-4:2.97-3.el8.x86_64 155/159 Installing : perl-inc-latest-2:0.500-9.el8.noarch 156/159 Installing : perl-Module-Build-2:0.42.24-5.el8.noarch 157/159 Installing : perl-CPAN-2.18-397.el8.noarch 158/159 Installing : perl-4:5.26.3-422.el8.x86_64 159/159 Running scriptlet: perl-4:5.26.3-422.el8.x86_64 159/159 Verifying : file-5.33-24.el8.x86_64 1/159 Verifying : glibc-gconv-extra-2.28-225.0.3.el8.x86_64 2/159 Verifying : groff-base-1.22.3-18.el8.x86_64 3/159 Verifying : perl-Algorithm-Diff-1.1903-9.el8.noarch 4/159 Verifying : perl-Archive-Tar-2.30-1.el8.noarch 5/159 Verifying : perl-Carp-1.42-396.el8.noarch 6/159 Verifying : perl-Compress-Raw-Bzip2-2.081-1.el8.x86_64 7/159 Verifying : perl-Compress-Raw-Zlib-2.081-1.el8.x86_64 8/159 Verifying : perl-Data-Dumper-2.167-399.el8.x86_64 9/159 Verifying : perl-Digest-1.17-395.el8.noarch 10/159 Verifying : perl-Digest-MD5-2.55-396.el8.x86_64 11/159 Verifying : perl-Encode-4:2.97-3.el8.x86_64 12/159 Verifying : perl-Errno-1.28-422.el8.x86_64 13/159 Verifying : perl-Exporter-5.72-396.el8.noarch 14/159 Verifying : perl-File-Path-2.15-2.el8.noarch 15/159 Verifying : perl-File-Temp-0.230.600-1.el8.noarch 16/159 Verifying : perl-Getopt-Long-1:2.50-4.el8.noarch 17/159 Verifying : perl-HTTP-Tiny-0.074-2.el8.noarch 18/159 Verifying : perl-IO-1.38-422.el8.x86_64 19/159 Verifying : perl-IO-Compress-2.081-1.el8.noarch 20/159 Verifying : perl-IO-Socket-IP-0.39-5.el8.noarch 21/159 Verifying : perl-IO-Zlib-1:1.10-422.el8.noarch 22/159 Verifying : perl-MIME-Base64-3.15-396.el8.x86_64 23/159 Verifying : perl-Math-BigInt-1:1.9998.11-7.el8.noarch 24/159 Verifying : perl-Math-Complex-1.59-422.el8.noarch 25/159 Verifying : perl-PathTools-3.74-1.el8.x86_64 26/159 Verifying : perl-Pod-Escapes-1:1.07-395.el8.noarch 27/159 Verifying : perl-Pod-Perldoc-3.28-396.el8.noarch 28/159 Verifying : perl-Pod-Simple-1:3.35-395.el8.noarch 29/159 Verifying : perl-Pod-Usage-4:1.69-395.el8.noarch 30/159 Verifying : perl-Scalar-List-Utils-3:1.49-2.el8.x86_64 31/159 Verifying : perl-Socket-4:2.027-3.el8.x86_64 32/159 Verifying : perl-Storable-1:3.11-3.el8.x86_64 33/159 Verifying : perl-Term-ANSIColor-4.06-396.el8.noarch 34/159 Verifying : perl-Term-Cap-1.17-395.el8.noarch 35/159 Verifying : perl-Text-Diff-1.45-2.el8.noarch 36/159 Verifying : perl-Text-ParseWords-3.30-395.el8.noarch 37/159 Verifying : perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch 38/159 Verifying : perl-Time-Local-1:1.280-1.el8.noarch 39/159 Verifying : perl-URI-1.73-3.el8.noarch 40/159 Verifying : perl-Unicode-Normalize-1.25-396.el8.x86_64 41/159 Verifying : perl-constant-1.33-396.el8.noarch 42/159 Verifying : perl-interpreter-4:5.26.3-422.el8.x86_64 43/159 Verifying : perl-libnet-3.11-3.el8.noarch 44/159 Verifying : perl-libs-4:5.26.3-422.el8.x86_64 45/159 Verifying : perl-macros-4:5.26.3-422.el8.x86_64 46/159 Verifying : perl-parent-1:0.237-1.el8.noarch 47/159 Verifying : perl-podlators-4.11-1.el8.noarch 48/159 Verifying : perl-threads-1:2.21-2.el8.x86_64 49/159 Verifying : perl-threads-shared-1.58-2.el8.x86_64 50/159 Verifying : python3-pyparsing-2.1.10-7.el8.noarch 51/159 Verifying : zip-3.0-23.el8.x86_64 52/159 Verifying : dwz-0.12-10.el8.x86_64 53/159 Verifying : efi-srpm-macros-3-3.0.1.el8.noarch 54/159 Verifying : ghc-srpm-macros-1.4.2-7.el8.noarch 55/159 Verifying : go-srpm-macros-2-17.el8.noarch 56/159 Verifying : ocaml-srpm-macros-5-4.el8.noarch 57/159 Verifying : openblas-srpm-macros-2-2.el8.noarch 58/159 Verifying : perl-4:5.26.3-422.el8.x86_64 59/159 Verifying : perl-Archive-Zip-1.60-3.el8.noarch 60/159 Verifying : perl-Attribute-Handlers-0.99-422.el8.noarch 61/159 Verifying : perl-B-Debug-1.26-2.el8.noarch 62/159 Verifying : perl-CPAN-2.18-397.el8.noarch 63/159 Verifying : perl-CPAN-Meta-2.150010-396.el8.noarch 64/159 Verifying : perl-CPAN-Meta-Requirements-2.140-396.el8.noarch 65/159 Verifying : perl-CPAN-Meta-YAML-0.018-397.el8.noarch 66/159 Verifying : perl-Compress-Bzip2-2.26-6.el8.x86_64 67/159 Verifying : perl-Config-Perl-V-0.30-1.el8.noarch 68/159 Verifying : perl-DB_File-1.842-1.el8.x86_64 69/159 Verifying : perl-Data-OptList-0.110-6.el8.noarch 70/159 Verifying : perl-Data-Section-0.200007-3.el8.noarch 71/159 Verifying : perl-Devel-PPPort-3.36-5.el8.x86_64 72/159 Verifying : perl-Devel-Peek-1.26-422.el8.x86_64 73/159 Verifying : perl-Devel-SelfStubber-1.06-422.el8.noarch 74/159 Verifying : perl-Devel-Size-0.81-2.el8.x86_64 75/159 Verifying : perl-Digest-SHA-1:6.02-1.el8.x86_64 76/159 Verifying : perl-Encode-Locale-1.05-10.module+el8.3.0+7692+5 77/159 Verifying : perl-Encode-devel-4:2.97-3.el8.x86_64 78/159 Verifying : perl-Env-1.04-395.el8.noarch 79/159 Verifying : perl-ExtUtils-CBuilder-1:0.280230-2.el8.noarch 80/159 Verifying : perl-ExtUtils-Command-1:7.34-1.el8.noarch 81/159 Verifying : perl-ExtUtils-Embed-1.34-422.el8.noarch 82/159 Verifying : perl-ExtUtils-Install-2.14-4.el8.noarch 83/159 Verifying : perl-ExtUtils-MM-Utils-1:7.34-1.el8.noarch 84/159 Verifying : perl-ExtUtils-MakeMaker-1:7.34-1.el8.noarch 85/159 Verifying : perl-ExtUtils-Manifest-1.70-395.el8.noarch 86/159 Verifying : perl-ExtUtils-Miniperl-1.06-422.el8.noarch 87/159 Verifying : perl-ExtUtils-ParseXS-1:3.35-2.el8.noarch 88/159 Verifying : perl-File-Fetch-0.56-2.el8.noarch 89/159 Verifying : perl-File-HomeDir-1.002-4.el8.noarch 90/159 Verifying : perl-File-Which-1.22-2.el8.noarch 91/159 Verifying : perl-Filter-2:1.58-2.el8.x86_64 92/159 Verifying : perl-Filter-Simple-0.94-2.el8.noarch 93/159 Verifying : perl-IO-Socket-SSL-2.066-4.module+el8.6.0+20623+ 94/159 Verifying : perl-IPC-Cmd-2:1.02-1.el8.noarch 95/159 Verifying : perl-IPC-SysV-2.07-397.el8.x86_64 96/159 Verifying : perl-IPC-System-Simple-1.25-17.el8.noarch 97/159 Verifying : perl-JSON-PP-1:2.97.001-3.el8.noarch 98/159 Verifying : perl-Locale-Codes-3.57-1.el8.noarch 99/159 Verifying : perl-Locale-Maketext-1.28-396.el8.noarch 100/159 Verifying : perl-Locale-Maketext-Simple-1:0.21-422.el8.noarc 101/159 Verifying : perl-MRO-Compat-0.13-4.el8.noarch 102/159 Verifying : perl-Math-BigInt-FastCalc-0.500.600-6.el8.x86_64 103/159 Verifying : perl-Math-BigRat-0.2614-1.el8.noarch 104/159 Verifying : perl-Memoize-1.03-422.el8.noarch 105/159 Verifying : perl-Module-Build-2:0.42.24-5.el8.noarch 106/159 Verifying : perl-Module-CoreList-1:5.20181130-1.el8.noarch 107/159 Verifying : perl-Module-CoreList-tools-1:5.20181130-1.el8.no 108/159 Verifying : perl-Module-Load-1:0.32-395.el8.noarch 109/159 Verifying : perl-Module-Load-Conditional-0.68-395.el8.noarch 110/159 Verifying : perl-Module-Loaded-1:0.08-422.el8.noarch 111/159 Verifying : perl-Module-Metadata-1.000033-395.el8.noarch 112/159 Verifying : perl-Mozilla-CA-20160104-7.0.1.module+el8.3.0+21 113/159 Verifying : perl-Net-Ping-2.55-422.el8.noarch 114/159 Verifying : perl-Net-SSLeay-1.88-2.module+el8.6.0+20623+f089 115/159 Verifying : perl-Package-Generator-1.106-11.el8.noarch 116/159 Verifying : perl-Params-Check-1:0.38-395.el8.noarch 117/159 Verifying : perl-Params-Util-1.07-22.el8.x86_64 118/159 Verifying : perl-Perl-OSType-1.010-396.el8.noarch 119/159 Verifying : perl-PerlIO-via-QuotedPrint-0.08-395.el8.noarch 120/159 Verifying : perl-Pod-Checker-4:1.73-395.el8.noarch 121/159 Verifying : perl-Pod-Html-1.22.02-422.el8.noarch 122/159 Verifying : perl-Pod-Parser-1.63-396.el8.noarch 123/159 Verifying : perl-SelfLoader-1.23-422.el8.noarch 124/159 Verifying : perl-Software-License-0.103013-2.el8.noarch 125/159 Verifying : perl-Sub-Exporter-0.987-15.el8.noarch 126/159 Verifying : perl-Sub-Install-0.928-14.el8.noarch 127/159 Verifying : perl-Sys-Syslog-0.35-397.el8.x86_64 128/159 Verifying : perl-TermReadKey-2.37-7.el8.x86_64 129/159 Verifying : perl-Test-1.30-422.el8.noarch 130/159 Verifying : perl-Test-Harness-1:3.42-1.el8.noarch 131/159 Verifying : perl-Test-Simple-1:1.302135-1.el8.noarch 132/159 Verifying : perl-Text-Balanced-2.03-395.el8.noarch 133/159 Verifying : perl-Text-Glob-0.11-4.el8.noarch 134/159 Verifying : perl-Text-Template-1.51-1.el8.noarch 135/159 Verifying : perl-Thread-Queue-3.13-1.el8.noarch 136/159 Verifying : perl-Time-HiRes-4:1.9758-2.el8.x86_64 137/159 Verifying : perl-Time-Piece-1.31-422.el8.x86_64 138/159 Verifying : perl-Unicode-Collate-1.25-2.el8.x86_64 139/159 Verifying : perl-autodie-2.29-396.el8.noarch 140/159 Verifying : perl-bignum-0.49-2.el8.noarch 141/159 Verifying : perl-devel-4:5.26.3-422.el8.x86_64 142/159 Verifying : perl-encoding-4:2.22-3.el8.x86_64 143/159 Verifying : perl-experimental-0.019-2.el8.noarch 144/159 Verifying : perl-inc-latest-2:0.500-9.el8.noarch 145/159 Verifying : perl-libnetcfg-4:5.26.3-422.el8.noarch 146/159 Verifying : perl-local-lib-2.000024-2.el8.noarch 147/159 Verifying : perl-open-1.11-422.el8.noarch 148/159 Verifying : perl-perlfaq-5.20180605-1.el8.noarch 149/159 Verifying : perl-srpm-macros-1-25.el8.noarch 150/159 Verifying : perl-utils-5.26.3-422.el8.noarch 151/159 Verifying : perl-version-6:0.99.24-1.el8.x86_64 152/159 Verifying : python-rpm-macros-3-45.el8.noarch 153/159 Verifying : python-srpm-macros-3-45.el8.noarch 154/159 Verifying : python3-rpm-macros-3-45.el8.noarch 155/159 Verifying : qt5-srpm-macros-5.15.3-1.el8.noarch 156/159 Verifying : redhat-rpm-config-131-1.0.1.el8.noarch 157/159 Verifying : rust-srpm-macros-5-2.el8.noarch 158/159 Verifying : systemtap-sdt-devel-4.9-3.0.1.el8.x86_64 159/159 Installed: dwz-0.12-10.el8.x86_64 efi-srpm-macros-3-3.0.1.el8.noarch file-5.33-24.el8.x86_64 ghc-srpm-macros-1.4.2-7.el8.noarch glibc-gconv-extra-2.28-225.0.3.el8.x86_64 go-srpm-macros-2-17.el8.noarch groff-base-1.22.3-18.el8.x86_64 ocaml-srpm-macros-5-4.el8.noarch openblas-srpm-macros-2-2.el8.noarch perl-4:5.26.3-422.el8.x86_64 perl-Algorithm-Diff-1.1903-9.el8.noarch perl-Archive-Tar-2.30-1.el8.noarch perl-Archive-Zip-1.60-3.el8.noarch perl-Attribute-Handlers-0.99-422.el8.noarch perl-B-Debug-1.26-2.el8.noarch perl-CPAN-2.18-397.el8.noarch perl-CPAN-Meta-2.150010-396.el8.noarch perl-CPAN-Meta-Requirements-2.140-396.el8.noarch perl-CPAN-Meta-YAML-0.018-397.el8.noarch perl-Carp-1.42-396.el8.noarch perl-Compress-Bzip2-2.26-6.el8.x86_64 perl-Compress-Raw-Bzip2-2.081-1.el8.x86_64 perl-Compress-Raw-Zlib-2.081-1.el8.x86_64 perl-Config-Perl-V-0.30-1.el8.noarch perl-DB_File-1.842-1.el8.x86_64 perl-Data-Dumper-2.167-399.el8.x86_64 perl-Data-OptList-0.110-6.el8.noarch perl-Data-Section-0.200007-3.el8.noarch perl-Devel-PPPort-3.36-5.el8.x86_64 perl-Devel-Peek-1.26-422.el8.x86_64 perl-Devel-SelfStubber-1.06-422.el8.noarch perl-Devel-Size-0.81-2.el8.x86_64 perl-Digest-1.17-395.el8.noarch perl-Digest-MD5-2.55-396.el8.x86_64 perl-Digest-SHA-1:6.02-1.el8.x86_64 perl-Encode-4:2.97-3.el8.x86_64 perl-Encode-Locale-1.05-10.module+el8.3.0+7692+542c56f9.noarch perl-Encode-devel-4:2.97-3.el8.x86_64 perl-Env-1.04-395.el8.noarch perl-Errno-1.28-422.el8.x86_64 perl-Exporter-5.72-396.el8.noarch perl-ExtUtils-CBuilder-1:0.280230-2.el8.noarch perl-ExtUtils-Command-1:7.34-1.el8.noarch perl-ExtUtils-Embed-1.34-422.el8.noarch perl-ExtUtils-Install-2.14-4.el8.noarch perl-ExtUtils-MM-Utils-1:7.34-1.el8.noarch perl-ExtUtils-MakeMaker-1:7.34-1.el8.noarch perl-ExtUtils-Manifest-1.70-395.el8.noarch perl-ExtUtils-Miniperl-1.06-422.el8.noarch perl-ExtUtils-ParseXS-1:3.35-2.el8.noarch perl-File-Fetch-0.56-2.el8.noarch perl-File-HomeDir-1.002-4.el8.noarch perl-File-Path-2.15-2.el8.noarch perl-File-Temp-0.230.600-1.el8.noarch perl-File-Which-1.22-2.el8.noarch perl-Filter-2:1.58-2.el8.x86_64 perl-Filter-Simple-0.94-2.el8.noarch perl-Getopt-Long-1:2.50-4.el8.noarch perl-HTTP-Tiny-0.074-2.el8.noarch perl-IO-1.38-422.el8.x86_64 perl-IO-Compress-2.081-1.el8.noarch perl-IO-Socket-IP-0.39-5.el8.noarch perl-IO-Socket-SSL-2.066-4.module+el8.6.0+20623+f0897f98.noarch perl-IO-Zlib-1:1.10-422.el8.noarch perl-IPC-Cmd-2:1.02-1.el8.noarch perl-IPC-SysV-2.07-397.el8.x86_64 perl-IPC-System-Simple-1.25-17.el8.noarch perl-JSON-PP-1:2.97.001-3.el8.noarch perl-Locale-Codes-3.57-1.el8.noarch perl-Locale-Maketext-1.28-396.el8.noarch perl-Locale-Maketext-Simple-1:0.21-422.el8.noarch perl-MIME-Base64-3.15-396.el8.x86_64 perl-MRO-Compat-0.13-4.el8.noarch perl-Math-BigInt-1:1.9998.11-7.el8.noarch perl-Math-BigInt-FastCalc-0.500.600-6.el8.x86_64 perl-Math-BigRat-0.2614-1.el8.noarch perl-Math-Complex-1.59-422.el8.noarch perl-Memoize-1.03-422.el8.noarch perl-Module-Build-2:0.42.24-5.el8.noarch perl-Module-CoreList-1:5.20181130-1.el8.noarch perl-Module-CoreList-tools-1:5.20181130-1.el8.noarch perl-Module-Load-1:0.32-395.el8.noarch perl-Module-Load-Conditional-0.68-395.el8.noarch perl-Module-Loaded-1:0.08-422.el8.noarch perl-Module-Metadata-1.000033-395.el8.noarch perl-Mozilla-CA-20160104-7.0.1.module+el8.3.0+21136+b437fca9.noarch perl-Net-Ping-2.55-422.el8.noarch perl-Net-SSLeay-1.88-2.module+el8.6.0+20623+f0897f98.x86_64 perl-Package-Generator-1.106-11.el8.noarch perl-Params-Check-1:0.38-395.el8.noarch perl-Params-Util-1.07-22.el8.x86_64 perl-PathTools-3.74-1.el8.x86_64 perl-Perl-OSType-1.010-396.el8.noarch perl-PerlIO-via-QuotedPrint-0.08-395.el8.noarch perl-Pod-Checker-4:1.73-395.el8.noarch perl-Pod-Escapes-1:1.07-395.el8.noarch perl-Pod-Html-1.22.02-422.el8.noarch perl-Pod-Parser-1.63-396.el8.noarch perl-Pod-Perldoc-3.28-396.el8.noarch perl-Pod-Simple-1:3.35-395.el8.noarch perl-Pod-Usage-4:1.69-395.el8.noarch perl-Scalar-List-Utils-3:1.49-2.el8.x86_64 perl-SelfLoader-1.23-422.el8.noarch perl-Socket-4:2.027-3.el8.x86_64 perl-Software-License-0.103013-2.el8.noarch perl-Storable-1:3.11-3.el8.x86_64 perl-Sub-Exporter-0.987-15.el8.noarch perl-Sub-Install-0.928-14.el8.noarch perl-Sys-Syslog-0.35-397.el8.x86_64 perl-Term-ANSIColor-4.06-396.el8.noarch perl-Term-Cap-1.17-395.el8.noarch perl-TermReadKey-2.37-7.el8.x86_64 perl-Test-1.30-422.el8.noarch perl-Test-Harness-1:3.42-1.el8.noarch perl-Test-Simple-1:1.302135-1.el8.noarch perl-Text-Balanced-2.03-395.el8.noarch perl-Text-Diff-1.45-2.el8.noarch perl-Text-Glob-0.11-4.el8.noarch perl-Text-ParseWords-3.30-395.el8.noarch perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch perl-Text-Template-1.51-1.el8.noarch perl-Thread-Queue-3.13-1.el8.noarch perl-Time-HiRes-4:1.9758-2.el8.x86_64 perl-Time-Local-1:1.280-1.el8.noarch perl-Time-Piece-1.31-422.el8.x86_64 perl-URI-1.73-3.el8.noarch perl-Unicode-Collate-1.25-2.el8.x86_64 perl-Unicode-Normalize-1.25-396.el8.x86_64 perl-autodie-2.29-396.el8.noarch perl-bignum-0.49-2.el8.noarch perl-constant-1.33-396.el8.noarch perl-devel-4:5.26.3-422.el8.x86_64 perl-encoding-4:2.22-3.el8.x86_64 perl-experimental-0.019-2.el8.noarch perl-inc-latest-2:0.500-9.el8.noarch perl-interpreter-4:5.26.3-422.el8.x86_64 perl-libnet-3.11-3.el8.noarch perl-libnetcfg-4:5.26.3-422.el8.noarch perl-libs-4:5.26.3-422.el8.x86_64 perl-local-lib-2.000024-2.el8.noarch perl-macros-4:5.26.3-422.el8.x86_64 perl-open-1.11-422.el8.noarch perl-parent-1:0.237-1.el8.noarch perl-perlfaq-5.20180605-1.el8.noarch perl-podlators-4.11-1.el8.noarch perl-srpm-macros-1-25.el8.noarch perl-threads-1:2.21-2.el8.x86_64 perl-threads-shared-1.58-2.el8.x86_64 perl-utils-5.26.3-422.el8.noarch perl-version-6:0.99.24-1.el8.x86_64 python-rpm-macros-3-45.el8.noarch python-srpm-macros-3-45.el8.noarch python3-pyparsing-2.1.10-7.el8.noarch python3-rpm-macros-3-45.el8.noarch qt5-srpm-macros-5.15.3-1.el8.noarch redhat-rpm-config-131-1.0.1.el8.noarch rust-srpm-macros-5-2.el8.noarch systemtap-sdt-devel-4.9-3.0.1.el8.x86_64 zip-3.0-23.el8.x86_64 Complete! |
I installed the python3 with this command:
dnf install -y python3 |
Display detailed console log →
Last metadata expiration check: 0:31:49 ago on Thu Dec 21 05:18:09 2023. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: python36 x86_64 3.6.8-38.module+el8.9.0+90104+968a3e84 ol8_appstream 18 k Installing dependencies: platform-python-pip noarch 9.0.3-23.el8 ol8_baseos_latest 1.6 M python3-pip noarch 9.0.3-23.el8 ol8_appstream 20 k python3-setuptools noarch 39.2.0-7.el8 ol8_baseos_latest 163 k Enabling module streams: python36 3.6 Transaction Summary ================================================================================ Install 4 Packages Total download size: 1.8 M Installed size: 7.0 M Downloading Packages: (1/4): python3-pip-9.0.3-23.el8.noarch.rpm 61 kB/s | 20 kB 00:00 (2/4): python36-3.6.8-38.module+el8.9.0+90104+9 229 kB/s | 18 kB 00:00 (3/4): python3-setuptools-39.2.0-7.el8.noarch.r 335 kB/s | 163 kB 00:00 (4/4): platform-python-pip-9.0.3-23.el8.noarch. 1.9 MB/s | 1.6 MB 00:00 -------------------------------------------------------------------------------- Total 2.2 MB/s | 1.8 MB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : python3-setuptools-39.2.0-7.el8.noarch 1/4 Installing : platform-python-pip-9.0.3-23.el8.noarch 2/4 Installing : python36-3.6.8-38.module+el8.9.0+90104+968a3e84.x86_ 3/4 Running scriptlet: python36-3.6.8-38.module+el8.9.0+90104+968a3e84.x86_ 3/4 Installing : python3-pip-9.0.3-23.el8.noarch 4/4 Running scriptlet: python3-pip-9.0.3-23.el8.noarch 4/4 Verifying : platform-python-pip-9.0.3-23.el8.noarch 1/4 Verifying : python3-setuptools-39.2.0-7.el8.noarch 2/4 Verifying : python3-pip-9.0.3-23.el8.noarch 3/4 Verifying : python36-3.6.8-38.module+el8.9.0+90104+968a3e84.x86_ 4/4 Installed: platform-python-pip-9.0.3-23.el8.noarch python3-pip-9.0.3-23.el8.noarch python3-setuptools-39.2.0-7.el8.noarch python36-3.6.8-38.module+el8.9.0+90104+968a3e84.x86_64 Complete! |
I installed the git module with this command:
dnf install -y git |
Display detailed console log →
Last metadata expiration check: 0:33:00 ago on Thu Dec 21 05:18:09 2023. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: git x86_64 2.39.3-1.el8_8 ol8_appstream 104 k Installing dependencies: emacs-filesystem noarch 1:26.1-11.el8 ol8_baseos_latest 70 k git-core x86_64 2.39.3-1.el8_8 ol8_appstream 11 M git-core-doc noarch 2.39.3-1.el8_8 ol8_appstream 3.0 M less x86_64 530-1.el8 ol8_baseos_latest 164 k perl-Error noarch 1:0.17025-2.el8 ol8_appstream 46 k perl-Git noarch 2.39.3-1.el8_8 ol8_appstream 79 k Transaction Summary ================================================================================ Install 7 Packages Total download size: 14 M Installed size: 45 M Downloading Packages: (1/7): git-2.39.3-1.el8_8.x86_64.rpm 233 kB/s | 104 kB 00:00 (2/7): emacs-filesystem-26.1-11.el8.noarch.rpm 155 kB/s | 70 kB 00:00 (3/7): less-530-1.el8.x86_64.rpm 309 kB/s | 164 kB 00:00 (4/7): perl-Error-0.17025-2.el8.noarch.rpm 519 kB/s | 46 kB 00:00 (5/7): perl-Git-2.39.3-1.el8_8.noarch.rpm 722 kB/s | 79 kB 00:00 (6/7): git-core-doc-2.39.3-1.el8_8.noarch.rpm 5.1 MB/s | 3.0 MB 00:00 (7/7): git-core-2.39.3-1.el8_8.x86_64.rpm 12 MB/s | 11 MB 00:00 -------------------------------------------------------------------------------- Total 11 MB/s | 14 MB 00:01 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : perl-Error-1:0.17025-2.el8.noarch 1/7 Installing : less-530-1.el8.x86_64 2/7 Installing : git-core-2.39.3-1.el8_8.x86_64 3/7 Installing : git-core-doc-2.39.3-1.el8_8.noarch 4/7 Installing : emacs-filesystem-1:26.1-11.el8.noarch 5/7 Installing : perl-Git-2.39.3-1.el8_8.noarch 6/7 Installing : git-2.39.3-1.el8_8.x86_64 7/7 Running scriptlet: git-2.39.3-1.el8_8.x86_64 7/7 Verifying : emacs-filesystem-1:26.1-11.el8.noarch 1/7 Verifying : less-530-1.el8.x86_64 2/7 Verifying : git-2.39.3-1.el8_8.x86_64 3/7 Verifying : git-core-2.39.3-1.el8_8.x86_64 4/7 Verifying : git-core-doc-2.39.3-1.el8_8.noarch 5/7 Verifying : perl-Error-1:0.17025-2.el8.noarch 6/7 Verifying : perl-Git-2.39.3-1.el8_8.noarch 7/7 Installed: emacs-filesystem-1:26.1-11.el8.noarch git-2.39.3-1.el8_8.x86_64 git-core-2.39.3-1.el8_8.x86_64 git-core-doc-2.39.3-1.el8_8.noarch less-530-1.el8.x86_64 perl-Error-1:0.17025-2.el8.noarch perl-Git-2.39.3-1.el8_8.noarch Complete! |
I installed the epel-release container with this command:
dnf install -y epel-release |
Display detailed console log →
Last metadata expiration check: 0:40:34 ago on Thu Dec 21 05:18:09 2023. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: oracle-epel-release-el8 x86_64 1.0-5.el8 ol8_baseos_latest 15 k Transaction Summary ================================================================================ Install 1 Package Total download size: 15 k Installed size: 18 k Downloading Packages: oracle-epel-release-el8-1.0-5.el8.x86_64.rpm 49 kB/s | 15 kB 00:00 -------------------------------------------------------------------------------- Total 49 kB/s | 15 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : oracle-epel-release-el8-1.0-5.el8.x86_64 1/1 Verifying : oracle-epel-release-el8-1.0-5.el8.x86_64 1/1 Installed: oracle-epel-release-el8-1.0-5.el8.x86_64 Complete! |
After installing all of these, you’re now ready to install the core rlwrap utility program. Like the other installations, you use:
dnf install -y rlwrap |
Display detailed console log →
Oracle Linux 8 EPEL Packages for Development (x 15 MB/s | 58 MB 00:03 Oracle Linux 8 EPEL Modular Packages for Develo 404 kB/s | 322 kB 00:00 Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: rlwrap x86_64 0.46.1-1.el8 ol8_developer_EPEL 140 k Installing dependencies: perl-File-Slurp noarch 9999.19-19.el8 ol8_appstream 47 k Transaction Summary ================================================================================ Install 2 Packages Total download size: 186 k Installed size: 426 k Downloading Packages: (1/2): perl-File-Slurp-9999.19-19.el8.noarch.rp 94 kB/s | 47 kB 00:00 (2/2): rlwrap-0.46.1-1.el8.x86_64.rpm 242 kB/s | 140 kB 00:00 -------------------------------------------------------------------------------- Total 321 kB/s | 186 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : perl-File-Slurp-9999.19-19.el8.noarch 1/2 Installing : rlwrap-0.46.1-1.el8.x86_64 2/2 Running scriptlet: rlwrap-0.46.1-1.el8.x86_64 2/2 Verifying : rlwrap-0.46.1-1.el8.x86_64 1/2 Verifying : perl-File-Slurp-9999.19-19.el8.noarch 2/2 Installed: perl-File-Slurp-9999.19-19.el8.noarch rlwrap-0.46.1-1.el8.x86_64 Complete! |
At this point, you need to create a sandboxed user account for the Docker instance because as a developer using the root user for simple tasks is a bad idea. While you could do this with a Docker command, the Oracle 23c Free edition raised a lock on the /etc/group file when I tried it. Naturally, that’s not a problem because you can connect as the root user with this syntax:
docker exec -it -u root oracle23c bash |
As the root user, create a student account as a developer account in the Oracle 23c Free container:
useradd -u 501 -g dba -G users -d /home/student -s /bin/bash/ -c "Student" -n student |
You’ll be unable to leverage the tnsnames.ora file unless you alter the prior command to replace dba with oinstall or add the following command:
usermod -a -G oinstall student |
Exit the Oracle 23c Free container as the root user and reconnect as the student user with this syntax:
docker exec -it --user student oracle23c bash |
While you’re connected as the root user, you should create an upload directory as a subdirectory of the $ORACLE_BASE directory. The $ORACLE_BASE directory in the Oracle Database 23c Free Docker image is the /opt/oracle directory.
You should use the following syntax to create the upload directory and change its permission to that of the Oracle Database 23c Free installation (for a future blog post on developing external table deployment on the Docker image):
mkdir /opt/oracle chown -R oracle:install /opt/oracle/upload |
You also can add the following student function to the Ubuntu student user’s .bashrc file. It means all you need to type to connect to the Oracle Database 23c Free Docker instance is “student“. I like shortcuts like this one, which let you leverage one-line Python commands.
student () { # Discover the fully qualified program name. path=`which docker 2>/dev/null` file='' # Parse the program name from the path. if [ -n ${path} ]; then file=${path##/*/} fi # Wrap when there is a file and it is rewrap. if [ -n ${file} ] && [[ ${file} = "docker" ]]; then python -c "import subprocess; subprocess.run(['docker exec -it --user student oracle23c bash'], shell=True)" else echo "Docker is unavailable: Install the docker package." fi } |
Open a Ubuntu Terminal shell and type a student function name to connect to the Docker Oracle Database 23c Free instance where you can now test things like external tables with the SQL*Plus command line without installing it on the Ubuntu local operating system.
student@student-virtual-machine:~$ student [student@d28375f0c43f ~]$ sqlplus c##student/student@free SQL*Plus: Release 23.0.0.0.0 - Production on Wed Jan 3 02:14:22 2024 Version 23.3.0.23.09 Copyright (c) 1982, 2023, Oracle. All rights reserved. Last Successful login time: Wed Jan 03 2024 01:56:44 +00:00 Connected to: Oracle Database 23c Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free Version 23.3.0.23.09 SQL> |
Then, I added this sqlplus function to the /home/student/.bashrc file, which is owned by the student user. However, I also added the instruction to change to the student user’s home directory because the Oracle 23c Free container will connect you to the /home/oracle directory by default. I also added the default long list (ll) alias to the .bashrc file.
sqlplus () { # Discover the fully qualified program name. path=`which rlwrap 2>/dev/null` file='' # Parse the program name from the path. if [ -n ${path} ]; then file=${path##/*/} fi; # Wrap when there is a file and it is rewrap. if [ -n ${file} ] && [[ ${file} = "rlwrap" ]]; then rlwrap sqlplus "${@}" else echo "Command-line history unavailable: Install the rlwrap package." $ORACLE_HOME/bin/sqlplus "${@}" fi } # Change to the user's home directory. cd ${HOME} # Create a long list alias: alias ll='ls -l --color=auto' |
After you’ve configured your student user, you can configure the oracle user account to work like a regular server. Exit the Docker Oracle Database 23c Free as the student user, then connect as the root user with this command:
docker exec -it -u root oracle23c bash |
As the root user you can become the oracle user with the following command:
su - oracle |
Now, add the following .bashrc shell in the /home/oracle directory:
# The oracle user's .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific environment if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]] then PATH="$HOME/.local/bin:$HOME/bin:$PATH" fi export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions export ORACLE_SID=FREE export ORACLE_BASE=/opt/oracle export ORACLE_HOME=/opt/oracle/product/23c/dbhomeFree export PATH=$PATH:/$ORACLE_HOME/bin # Change to the user's home directory. cd ${HOME} # Create a long list alias: alias ll='ls -l --color=auto' sqlplus () { # Discover the fully qualified program name. path=`which rlwrap 2>/dev/null` file='' # Parse the program name from the path. if [ -n ${path} ]; then file=${path##/*/} fi; # Wrap when there is a file and it is rewrap. if [ -n ${file} ] && [[ ${file} = "rlwrap" ]]; then rlwrap sqlplus "${@}" else echo "Command-line history unavailable: Install the rlwrap package." $ORACLE_HOME/bin/sqlplus "${@}" fi } |
You need to manually source the .bashrc for the oracle user because it’s not an externally available user. Use this syntax to connect as the internal user:
sqlplus / as sysdba |
It’ll display:
SQL*Plus: RELEASE 23.0.0.0.0 - Production ON Wed Jan 3 07:08:11 2024 Version 23.3.0.23.09 Copyright (c) 1982, 2023, Oracle. ALL rights reserved. Connected TO: Oracle DATABASE 23c Free RELEASE 23.0.0.0.0 - Develop, Learn, AND Run FOR Free Version 23.3.0.23.09 SQL> |
After all this, I can now click the “up arrow” to edit any of the sqlplus command history. If you like to work inside sqlplus natively, this should help you.
OracleDB Python Tutorial 1
This shows you how to get Python working with the Oracle Database 23c in Docker or Podman on Ubuntu. You can find useful connection strings for this in Oracle Database Free Get Started.
- First step requires you to install the pip3/span> utility on Ubuntu.
sudo apt install -y python3-pip
Display detailed console log →
Reading package lists... Done Building dependency tree... Done Reading state information... Done The following additional packages will be installed: binutils binutils-common binutils-x86-64-linux-gnu build-essential dpkg-dev fakeroot g++ g++-11 gcc gcc-11 javascript-common libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan6 libbinutils libc-dev-bin libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-11-dev libitm1 libjs-jquery libjs-sphinxdoc libjs-underscore liblsan0 libnsl-dev libpython3-dev libpython3.10-dev libquadmath0 libstdc++-11-dev libtirpc-dev libtsan0 libubsan1 linux-libc-dev lto-disabled-list make manpages-dev python3-dev python3-distutils python3-setuptools python3-wheel python3.10-dev rpcsvc-proto zlib1g-dev Suggested packages: binutils-doc debian-keyring g++-multilib g++-11-multilib gcc-11-doc gcc-multilib autoconf automake libtool flex bison gcc-doc gcc-11-multilib gcc-11-locales apache2 | lighttpd | httpd glibc-doc bzr libstdc++-11-doc make-doc python-setuptools-doc The following NEW packages will be installed: binutils binutils-common binutils-x86-64-linux-gnu build-essential dpkg-dev fakeroot g++ g++-11 gcc gcc-11 javascript-common libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan6 libbinutils libc-dev-bin libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-11-dev libitm1 libjs-jquery libjs-sphinxdoc libjs-underscore liblsan0 libnsl-dev libpython3-dev libpython3.10-dev libquadmath0 libstdc++-11-dev libtirpc-dev libtsan0 libubsan1 linux-libc-dev lto-disabled-list make manpages-dev python3-dev python3-distutils python3-pip python3-setuptools python3-wheel python3.10-dev rpcsvc-proto zlib1g-dev 0 upgraded, 53 newly installed, 0 to remove and 9 not upgraded. Need to get 62.2 MB of archives. After this operation, 220 MB of additional disk space will be used. Get:1 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils-common amd64 2.38-4ubuntu2.3 [222 kB] Get:2 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libbinutils amd64 2.38-4ubuntu2.3 [662 kB] Get:3 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libctf-nobfd0 amd64 2.38-4ubuntu2.3 [107 kB] Get:4 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libctf0 amd64 2.38-4ubuntu2.3 [103 kB] Get:5 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils-x86-64-linux-gnu amd64 2.38-4ubuntu2.3 [2,327 kB] Get:6 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils amd64 2.38-4ubuntu2.3 [3,190 B] Get:7 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc-dev-bin amd64 2.35-0ubuntu3.5 [20.3 kB] Get:8 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 linux-libc-dev amd64 5.15.0-91.101 [1,332 kB] Get:9 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libcrypt-dev amd64 1:4.4.27-1 [112 kB] Get:10 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 rpcsvc-proto amd64 1.4.2-0ubuntu6 [68.5 kB] Get:11 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libtirpc-dev amd64 1.3.2-2ubuntu0.1 [192 kB] Get:12 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libnsl-dev amd64 1.3.0-2build2 [71.3 kB] Get:13 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc6-dev amd64 2.35-0ubuntu3.5 [2,098 kB] Get:14 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libcc1-0 amd64 12.3.0-1ubuntu1~22.04 [48.3 kB] Get:15 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libitm1 amd64 12.3.0-1ubuntu1~22.04 [30.2 kB] Get:16 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libasan6 amd64 11.4.0-1ubuntu1~22.04 [2,282 kB] Get:17 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 liblsan0 amd64 12.3.0-1ubuntu1~22.04 [1,069 kB] Get:18 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libtsan0 amd64 11.4.0-1ubuntu1~22.04 [2,260 kB] Get:19 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libubsan1 amd64 12.3.0-1ubuntu1~22.04 [976 kB] Get:20 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libquadmath0 amd64 12.3.0-1ubuntu1~22.04 [154 kB] Get:21 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgcc-11-dev amd64 11.4.0-1ubuntu1~22.04 [2,517 kB] Get:22 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 gcc-11 amd64 11.4.0-1ubuntu1~22.04 [20.1 MB] Get:23 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 gcc amd64 4:11.2.0-1ubuntu1 [5,112 B] Get:24 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libstdc++-11-dev amd64 11.4.0-1ubuntu1~22.04 [2,101 kB] Get:25 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 g++-11 amd64 11.4.0-1ubuntu1~22.04 [11.4 MB] Get:26 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 g++ amd64 4:11.2.0-1ubuntu1 [1,412 B] Get:27 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 make amd64 4.3-4.1build1 [180 kB] Get:28 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libdpkg-perl all 1.21.1ubuntu2.2 [237 kB] Get:29 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 lto-disabled-list all 24 [12.5 kB] Get:30 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 dpkg-dev all 1.21.1ubuntu2.2 [922 kB] Get:31 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 build-essential amd64 12.9ubuntu3 [4,744 B] Get:32 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libfakeroot amd64 1.28-1ubuntu1 [31.5 kB] Get:33 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 fakeroot amd64 1.28-1ubuntu1 [60.4 kB] Get:34 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 javascript-common all 11+nmu1 [5,936 B] Get:35 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-diff-perl all 1.201-1 [41.8 kB] Get:36 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-diff-xs-perl amd64 0.04-6build3 [11.9 kB] Get:37 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-merge-perl all 0.08-3 [12.0 kB] Get:38 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc-devtools amd64 2.35-0ubuntu3.5 [28.9 kB] Get:39 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libexpat1-dev amd64 2.4.7-1ubuntu0.2 [147 kB] Get:40 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libfile-fcntllock-perl amd64 0.22-3build7 [33.9 kB] Get:41 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libjs-jquery all 3.6.0+dfsg+~3.5.13-1 [321 kB] Get:42 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libjs-underscore all 1.13.2~dfsg-2 [118 kB] Get:43 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 libjs-sphinxdoc all 4.3.2-1 [139 kB] Get:44 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 zlib1g-dev amd64 1:1.2.11.dfsg-2ubuntu9.2 [164 kB] Get:45 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3.10-dev amd64 3.10.12-1~22.04.3 [4,762 kB] Get:46 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3-dev amd64 3.10.6-1~22.04 [7,166 B] Get:47 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 manpages-dev all 5.10-1ubuntu1 [2,309 kB] Get:48 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3.10-dev amd64 3.10.12-1~22.04.3 [507 kB] Get:49 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-distutils all 3.10.8-1~22.04 [139 kB] Get:50 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-dev amd64 3.10.6-1~22.04 [26.0 kB] Get:51 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-setuptools all 59.6.0-1.2ubuntu0.22.04.1 [339 kB] Get:52 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 python3-wheel all 0.37.1-2ubuntu0.22.04.1 [32.0 kB] Get:53 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 python3-pip all 22.0.2+dfsg-1ubuntu0.4 [1,305 kB] Fetched 62.2 MB in 35s (1,781 kB/s) Extracting templates from packages: 100% Selecting previously unselected package binutils-common:amd64. (Reading database ... 221117 files and directories currently installed.) Preparing to unpack .../00-binutils-common_2.38-4ubuntu2.3_amd64.deb ... Unpacking binutils-common:amd64 (2.38-4ubuntu2.3) ... Selecting previously unselected package libbinutils:amd64. Preparing to unpack .../01-libbinutils_2.38-4ubuntu2.3_amd64.deb ... Unpacking libbinutils:amd64 (2.38-4ubuntu2.3) ... Selecting previously unselected package libctf-nobfd0:amd64. Preparing to unpack .../02-libctf-nobfd0_2.38-4ubuntu2.3_amd64.deb ... Unpacking libctf-nobfd0:amd64 (2.38-4ubuntu2.3) ... Selecting previously unselected package libctf0:amd64. Preparing to unpack .../03-libctf0_2.38-4ubuntu2.3_amd64.deb ... Unpacking libctf0:amd64 (2.38-4ubuntu2.3) ... Selecting previously unselected package binutils-x86-64-linux-gnu. Preparing to unpack .../04-binutils-x86-64-linux-gnu_2.38-4ubuntu2.3_amd64.deb ... Unpacking binutils-x86-64-linux-gnu (2.38-4ubuntu2.3) ... Selecting previously unselected package binutils. Preparing to unpack .../05-binutils_2.38-4ubuntu2.3_amd64.deb ... Unpacking binutils (2.38-4ubuntu2.3) ... Selecting previously unselected package libc-dev-bin. Preparing to unpack .../06-libc-dev-bin_2.35-0ubuntu3.5_amd64.deb ... Unpacking libc-dev-bin (2.35-0ubuntu3.5) ... Selecting previously unselected package linux-libc-dev:amd64. Preparing to unpack .../07-linux-libc-dev_5.15.0-91.101_amd64.deb ... Unpacking linux-libc-dev:amd64 (5.15.0-91.101) ... Selecting previously unselected package libcrypt-dev:amd64. Preparing to unpack .../08-libcrypt-dev_1%3a4.4.27-1_amd64.deb ... Unpacking libcrypt-dev:amd64 (1:4.4.27-1) ... Selecting previously unselected package rpcsvc-proto. Preparing to unpack .../09-rpcsvc-proto_1.4.2-0ubuntu6_amd64.deb ... Unpacking rpcsvc-proto (1.4.2-0ubuntu6) ... Selecting previously unselected package libtirpc-dev:amd64. Preparing to unpack .../10-libtirpc-dev_1.3.2-2ubuntu0.1_amd64.deb ... Unpacking libtirpc-dev:amd64 (1.3.2-2ubuntu0.1) ... Selecting previously unselected package libnsl-dev:amd64. Preparing to unpack .../11-libnsl-dev_1.3.0-2build2_amd64.deb ... Unpacking libnsl-dev:amd64 (1.3.0-2build2) ... Selecting previously unselected package libc6-dev:amd64. Preparing to unpack .../12-libc6-dev_2.35-0ubuntu3.5_amd64.deb ... Unpacking libc6-dev:amd64 (2.35-0ubuntu3.5) ... Selecting previously unselected package libcc1-0:amd64. Preparing to unpack .../13-libcc1-0_12.3.0-1ubuntu1~22.04_amd64.deb ... Unpacking libcc1-0:amd64 (12.3.0-1ubuntu1~22.04) ... Selecting previously unselected package libitm1:amd64. Preparing to unpack .../14-libitm1_12.3.0-1ubuntu1~22.04_amd64.deb ... Unpacking libitm1:amd64 (12.3.0-1ubuntu1~22.04) ... Selecting previously unselected package libasan6:amd64. Preparing to unpack .../15-libasan6_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking libasan6:amd64 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package liblsan0:amd64. Preparing to unpack .../16-liblsan0_12.3.0-1ubuntu1~22.04_amd64.deb ... Unpacking liblsan0:amd64 (12.3.0-1ubuntu1~22.04) ... Selecting previously unselected package libtsan0:amd64. Preparing to unpack .../17-libtsan0_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking libtsan0:amd64 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package libubsan1:amd64. Preparing to unpack .../18-libubsan1_12.3.0-1ubuntu1~22.04_amd64.deb ... Unpacking libubsan1:amd64 (12.3.0-1ubuntu1~22.04) ... Selecting previously unselected package libquadmath0:amd64. Preparing to unpack .../19-libquadmath0_12.3.0-1ubuntu1~22.04_amd64.deb ... Unpacking libquadmath0:amd64 (12.3.0-1ubuntu1~22.04) ... Selecting previously unselected package libgcc-11-dev:amd64. Preparing to unpack .../20-libgcc-11-dev_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking libgcc-11-dev:amd64 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package gcc-11. Preparing to unpack .../21-gcc-11_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking gcc-11 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package gcc. Preparing to unpack .../22-gcc_4%3a11.2.0-1ubuntu1_amd64.deb ... Unpacking gcc (4:11.2.0-1ubuntu1) ... Selecting previously unselected package libstdc++-11-dev:amd64. Preparing to unpack .../23-libstdc++-11-dev_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking libstdc++-11-dev:amd64 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package g++-11. Preparing to unpack .../24-g++-11_11.4.0-1ubuntu1~22.04_amd64.deb ... Unpacking g++-11 (11.4.0-1ubuntu1~22.04) ... Selecting previously unselected package g++. Preparing to unpack .../25-g++_4%3a11.2.0-1ubuntu1_amd64.deb ... Unpacking g++ (4:11.2.0-1ubuntu1) ... Selecting previously unselected package make. Preparing to unpack .../26-make_4.3-4.1build1_amd64.deb ... Unpacking make (4.3-4.1build1) ... Selecting previously unselected package libdpkg-perl. Preparing to unpack .../27-libdpkg-perl_1.21.1ubuntu2.2_all.deb ... Unpacking libdpkg-perl (1.21.1ubuntu2.2) ... Selecting previously unselected package lto-disabled-list. Preparing to unpack .../28-lto-disabled-list_24_all.deb ... Unpacking lto-disabled-list (24) ... Selecting previously unselected package dpkg-dev. Preparing to unpack .../29-dpkg-dev_1.21.1ubuntu2.2_all.deb ... Unpacking dpkg-dev (1.21.1ubuntu2.2) ... Selecting previously unselected package build-essential. Preparing to unpack .../30-build-essential_12.9ubuntu3_amd64.deb ... Unpacking build-essential (12.9ubuntu3) ... Selecting previously unselected package libfakeroot:amd64. Preparing to unpack .../31-libfakeroot_1.28-1ubuntu1_amd64.deb ... Unpacking libfakeroot:amd64 (1.28-1ubuntu1) ... Selecting previously unselected package fakeroot. Preparing to unpack .../32-fakeroot_1.28-1ubuntu1_amd64.deb ... Unpacking fakeroot (1.28-1ubuntu1) ... Selecting previously unselected package javascript-common. Preparing to unpack .../33-javascript-common_11+nmu1_all.deb ... Unpacking javascript-common (11+nmu1) ... Selecting previously unselected package libalgorithm-diff-perl. Preparing to unpack .../34-libalgorithm-diff-perl_1.201-1_all.deb ... Unpacking libalgorithm-diff-perl (1.201-1) ... Selecting previously unselected package libalgorithm-diff-xs-perl. Preparing to unpack .../35-libalgorithm-diff-xs-perl_0.04-6build3_amd64.deb ... Unpacking libalgorithm-diff-xs-perl (0.04-6build3) ... Selecting previously unselected package libalgorithm-merge-perl. Preparing to unpack .../36-libalgorithm-merge-perl_0.08-3_all.deb ... Unpacking libalgorithm-merge-perl (0.08-3) ... Selecting previously unselected package libc-devtools. Preparing to unpack .../37-libc-devtools_2.35-0ubuntu3.5_amd64.deb ... Unpacking libc-devtools (2.35-0ubuntu3.5) ... Selecting previously unselected package libexpat1-dev:amd64. Preparing to unpack .../38-libexpat1-dev_2.4.7-1ubuntu0.2_amd64.deb ... Unpacking libexpat1-dev:amd64 (2.4.7-1ubuntu0.2) ... Selecting previously unselected package libfile-fcntllock-perl. Preparing to unpack .../39-libfile-fcntllock-perl_0.22-3build7_amd64.deb ... Unpacking libfile-fcntllock-perl (0.22-3build7) ... Selecting previously unselected package libjs-jquery. Preparing to unpack .../40-libjs-jquery_3.6.0+dfsg+~3.5.13-1_all.deb ... Unpacking libjs-jquery (3.6.0+dfsg+~3.5.13-1) ... Selecting previously unselected package libjs-underscore. Preparing to unpack .../41-libjs-underscore_1.13.2~dfsg-2_all.deb ... Unpacking libjs-underscore (1.13.2~dfsg-2) ... Selecting previously unselected package libjs-sphinxdoc. Preparing to unpack .../42-libjs-sphinxdoc_4.3.2-1_all.deb ... Unpacking libjs-sphinxdoc (4.3.2-1) ... Selecting previously unselected package zlib1g-dev:amd64. Preparing to unpack .../43-zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu9.2_amd64.deb ... Unpacking zlib1g-dev:amd64 (1:1.2.11.dfsg-2ubuntu9.2) ... Selecting previously unselected package libpython3.10-dev:amd64. Preparing to unpack .../44-libpython3.10-dev_3.10.12-1~22.04.3_amd64.deb ... Unpacking libpython3.10-dev:amd64 (3.10.12-1~22.04.3) ... Selecting previously unselected package libpython3-dev:amd64. Preparing to unpack .../45-libpython3-dev_3.10.6-1~22.04_amd64.deb ... Unpacking libpython3-dev:amd64 (3.10.6-1~22.04) ... Selecting previously unselected package manpages-dev. Preparing to unpack .../46-manpages-dev_5.10-1ubuntu1_all.deb ... Unpacking manpages-dev (5.10-1ubuntu1) ... Selecting previously unselected package python3.10-dev. Preparing to unpack .../47-python3.10-dev_3.10.12-1~22.04.3_amd64.deb ... Unpacking python3.10-dev (3.10.12-1~22.04.3) ... Selecting previously unselected package python3-distutils. Preparing to unpack .../48-python3-distutils_3.10.8-1~22.04_all.deb ... Unpacking python3-distutils (3.10.8-1~22.04) ... Selecting previously unselected package python3-dev. Preparing to unpack .../49-python3-dev_3.10.6-1~22.04_amd64.deb ... Unpacking python3-dev (3.10.6-1~22.04) ... Selecting previously unselected package python3-setuptools. Preparing to unpack .../50-python3-setuptools_59.6.0-1.2ubuntu0.22.04.1_all.deb ... Unpacking python3-setuptools (59.6.0-1.2ubuntu0.22.04.1) ... Selecting previously unselected package python3-wheel. Preparing to unpack .../51-python3-wheel_0.37.1-2ubuntu0.22.04.1_all.deb ... Unpacking python3-wheel (0.37.1-2ubuntu0.22.04.1) ... Selecting previously unselected package python3-pip. Preparing to unpack .../52-python3-pip_22.0.2+dfsg-1ubuntu0.4_all.deb ... Unpacking python3-pip (22.0.2+dfsg-1ubuntu0.4) ... Setting up python3-distutils (3.10.8-1~22.04) ... Setting up javascript-common (11+nmu1) ... Setting up manpages-dev (5.10-1ubuntu1) ... Setting up lto-disabled-list (24) ... Setting up python3-setuptools (59.6.0-1.2ubuntu0.22.04.1) ... Setting up libfile-fcntllock-perl (0.22-3build7) ... Setting up libalgorithm-diff-perl (1.201-1) ... Setting up binutils-common:amd64 (2.38-4ubuntu2.3) ... Setting up linux-libc-dev:amd64 (5.15.0-91.101) ... Setting up libctf-nobfd0:amd64 (2.38-4ubuntu2.3) ... Setting up python3-wheel (0.37.1-2ubuntu0.22.04.1) ... Setting up libfakeroot:amd64 (1.28-1ubuntu1) ... Setting up libasan6:amd64 (11.4.0-1ubuntu1~22.04) ... Setting up fakeroot (1.28-1ubuntu1) ... update-alternatives: using /usr/bin/fakeroot-sysv to provide /usr/bin/fakeroot (fakeroot) in auto mode Setting up libtirpc-dev:amd64 (1.3.2-2ubuntu0.1) ... Setting up rpcsvc-proto (1.4.2-0ubuntu6) ... Setting up make (4.3-4.1build1) ... Setting up libquadmath0:amd64 (12.3.0-1ubuntu1~22.04) ... Setting up python3-pip (22.0.2+dfsg-1ubuntu0.4) ... Setting up libdpkg-perl (1.21.1ubuntu2.2) ... Setting up libubsan1:amd64 (12.3.0-1ubuntu1~22.04) ... Setting up libnsl-dev:amd64 (1.3.0-2build2) ... Setting up libcrypt-dev:amd64 (1:4.4.27-1) ... Setting up libjs-jquery (3.6.0+dfsg+~3.5.13-1) ... Setting up libbinutils:amd64 (2.38-4ubuntu2.3) ... Setting up libc-dev-bin (2.35-0ubuntu3.5) ... Setting up libalgorithm-diff-xs-perl (0.04-6build3) ... Setting up libcc1-0:amd64 (12.3.0-1ubuntu1~22.04) ... Setting up liblsan0:amd64 (12.3.0-1ubuntu1~22.04) ... Setting up libitm1:amd64 (12.3.0-1ubuntu1~22.04) ... Setting up libc-devtools (2.35-0ubuntu3.5) ... Setting up libjs-underscore (1.13.2~dfsg-2) ... Setting up libalgorithm-merge-perl (0.08-3) ... Setting up libtsan0:amd64 (11.4.0-1ubuntu1~22.04) ... Setting up libctf0:amd64 (2.38-4ubuntu2.3) ... Setting up libjs-sphinxdoc (4.3.2-1) ... Setting up libgcc-11-dev:amd64 (11.4.0-1ubuntu1~22.04) ... Setting up libc6-dev:amd64 (2.35-0ubuntu3.5) ... Setting up binutils-x86-64-linux-gnu (2.38-4ubuntu2.3) ... Setting up binutils (2.38-4ubuntu2.3) ... Setting up dpkg-dev (1.21.1ubuntu2.2) ... Setting up libexpat1-dev:amd64 (2.4.7-1ubuntu0.2) ... Setting up libstdc++-11-dev:amd64 (11.4.0-1ubuntu1~22.04) ... Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-2ubuntu9.2) ... Setting up gcc-11 (11.4.0-1ubuntu1~22.04) ... Setting up g++-11 (11.4.0-1ubuntu1~22.04) ... Setting up gcc (4:11.2.0-1ubuntu1) ... Setting up libpython3.10-dev:amd64 (3.10.12-1~22.04.3) ... Setting up python3.10-dev (3.10.12-1~22.04.3) ... Setting up g++ (4:11.2.0-1ubuntu1) ... update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode Setting up build-essential (12.9ubuntu3) ... Setting up libpython3-dev:amd64 (3.10.6-1~22.04) ... Setting up python3-dev (3.10.6-1~22.04) ... Processing triggers for man-db (2.10.2-1) ... Processing triggers for libc-bin (2.35-0ubuntu3.5) ...
- Second step requires that you pip3 install the oracledb library:
sudo pip3 install oracledb --upgrade
Display detailed console log →
Defaulting to user installation because normal site-packages is not writeable Collecting oracledb Downloading oracledb-1.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.6 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.6/8.6 MB 2.7 MB/s eta 0:00:00 Requirement already satisfied: cryptography>=3.2.1 in /usr/lib/python3/dist-packages (from oracledb) (3.4.8) Installing collected packages: oracledb Successfully installed oracledb-1.4.2
- Third step requires you write a Python program to test your connection to Oracle Database 23c Free, like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#!/usr/bin/python # Import the Oracle library. import oracledb try: # Create a connection to local Docker or Podman installation. db = oracledb.connect(user='c##student', password='student', dsn='localhost:51521/FREE') # Print a connection message. print("Connected to the Oracle", db.version, "database.") except oracledb.DatabaseError as e: error, = e.args print(sys.stderr, "Oracle-Error-Code:", error.code) print(sys.stderr, "Oracle-Error-Message:", error.message) finally: # Close connection. db.close()
The 51521 port is the recommended port when setting up Docker or Podman services, however, it can be set to any port above 1024.
It should print:
Connected to the Oracle 23.3.0.23.9 database.
- Fourth step requires you write a Python program to test querying data from an Oracle Database 23c Free instance. I created the following avenger table and seeded it with six Avengers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* Conditionally drop the table. */ DROP TABLE IF EXISTS avenger; /* Create the table. */ CREATE TABLE avenger ( avenger_id NUMBER , first_name VARCHAR2(20) , last_name VARCHAR2(20) , character_name VARCHAR2(20)); /* Seed the table with data. */ INSERT INTO avenger VALUES (1,'Anthony','Stark','Iron Man'); INSERT INTO avenger VALUES (2,'Thor','Odinson','God of Thunder'); INSERT INTO avenger VALUES (3,'Steven','Rogers','Captain America'); INSERT INTO avenger VALUES (4,'Bruce','Banner','Hulk'); INSERT INTO avenger VALUES (5,'Clinton','Barton','Hawkeye'); INSERT INTO avenger VALUES (6,'Natasha','Romanoff','Black Widow');
Then, I extended the program logic to include a cursor and for loop to read the values from the avenger table:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#!/usr/bin/python # Import the Oracle library. import oracledb try: # Create a connection to local Docker or Podman installation. db = oracledb.connect(user='c##student', password='student', dsn='localhost:51521/FREE') # Create a cursor. cursor = db.cursor() # Execute a query. cursor.execute("SELECT character_name " + ", first_name " + ", last_name " + "FROM avenger " + "ORDER BY character_name") # Read the contents of the cursor. for row in cursor: print(row[0] + ':',row[2] + ',',row[1]) except oracledb.DatabaseError as e: error, = e.args print(sys.stderr, "Oracle-Error-Code:", error.code) print(sys.stderr, "Oracle-Error-Message:", error.message) finally: # Close cursor and connection. cursor.close() db.close()
The 51521 port is the recommended port when setting up Docker or Podman services, however, it can be set to any port above 1024.
It should print:
Black Widow: Romanoff, Natasha Captain America: Rogers, Steven God of Thunder: Odinson, Thor Hawkeye: Barton, Clinton Hulk: Banner, Bruce Iron Man: Stark, Anthony
- Fifth step requires you write a Python program to test querying data filtered by a local variable from an Oracle Database 23c Free instance. This example looks only for the Hulk among the six Avengers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#!/usr/bin/python # Import the Oracle library. import oracledb try: # Create a connection to local Docker or Podman installation. db = oracledb.connect(user='c##student', password='student', dsn='localhost:51521/FREE') # Create a cursor. cursor = db.cursor() # Execute a query. stmt = "SELECT character_name " \ ", first_name " \ ", last_name " \ "FROM avenger " \ "WHERE character_name = :avenger " \ "ORDER BY character_name" # Execute with bind variable. cursor.execute(stmt, avenger = "Hulk") # Read the contents of the cursor. for row in cursor: print(row[0] + ':',row[2] + ',',row[1]) except oracledb.DatabaseError as e: error, = e.args print(sys.stderr, "Oracle-Error-Code:", error.code) print(sys.stderr, "Oracle-Error-Message:", error.message) finally: # Close cursor and connection. cursor.close() db.close()
It should print:
Hulk: Banner, Bruce
As always, I hope this puts everything together for setting up Python with Oracle Database 23c Free.
Python3 on PostgreSQL
The necessary Python 3 driver for connections to the PostgreSQL database is python3-psycopg2, as qualified by this earlier post with full test examples for Red Hat distributions. You can install it on Ubuntu with the following command:
sudo apt-get install -y python3-psycopg2 |
Display detailed console log →
python3-psycopg2 Reading package lists... Done Building dependency tree... Done Reading state information... Done Suggested packages: python-psycopg2-doc The following NEW packages will be installed: python3-psycopg2 0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded. Need to get 136 kB of archives. After this operation, 483 kB of additional disk space will be used. Get:1 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 python3-psycopg2 amd64 2.9.2-1build2 [136 kB] Fetched 136 kB in 1s (146 kB/s) Selecting previously unselected package python3-psycopg2. (Reading database ... 204321 files and directories currently installed.) Preparing to unpack .../python3-psycopg2_2.9.2-1build2_amd64.deb ... Unpacking python3-psycopg2 (2.9.2-1build2) ... Setting up python3-psycopg2 (2.9.2-1build2) ... |
As always, I hope this helps those looking for a solution. Also, remember the referenced post above provides Linux distribution neutral full solutions.
MySQL on Ubuntu
Working with my students to create an Ubuntu virtual environment for Python development with the MySQL database. After completing the general provisioning covered in this older post, I’d recommend you create a python symbolic link before installing the MySQL-Python driver.
sudo ln -s /usr/bin/python3 /usr/bin/python |
You install the Python development driver with the following:
sudo apt-get -y install python3-mysql.connector |
Create a python_connect.py file to test your Python deployment’s ability to connect to the MySQL database:
#!/usr/bin/python # Import the library. import mysql.connector from mysql.connector import errorcode try: # Open connection. cnx = mysql.connector.connect(user='student', password='student', host='localhost', database='sakila') # Print the value. print("Database connection resolved.") # Handle exception and close connection. except mysql.connector.Error as e: if e.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif e.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") else: print(e) # Close the connection when the try block completes. else: cnx.close() |
You should change the file permissions of the python_connect.py to read-write-execute as owner, and read-execute as group and other with the following command:
chmod 755 python_connect.py |
Then, you can test your python_connect.py program from the local directory with the following command:
./python_connect.py |
You see the following output if it works:
Database connection resolved. |
As alway, I hope those looking for a code complete solutionk