Install EasyGUI on Fedora
The EasyGUI library is a nice tool for developing GUI applications. It doesn’t require you to know event-driven programming to write basic GUI applications because it’s based on Python functions.
You can download and install the EasyGUI library with yum utility like this:
yum install -y python-easygui |
It should generate the following list:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00 mysql-tools-community | 2.5 kB 00:00 mysql56-community | 2.5 kB 00:00 pgdg93 | 3.6 kB 00:00 updates/20/x86_64/metalink | 2.8 kB 00:00 Resolving Dependencies --> Running transaction check ---> Package python-easygui.noarch 0:0.96-7.fc20 will be installed --> Processing Dependency: tkinter for package: python-easygui-0.96-7.fc20.noarch --> Processing Dependency: python-setuptools for package: python-easygui-0.96-7.fc20.noarch --> Running transaction check ---> Package python-setuptools.noarch 0:1.4.2-1.fc20 will be installed ---> Package tkinter.x86_64 0:2.7.5-16.fc20 will be installed --> Processing Dependency: libtk8.5.so()(64bit) for package: tkinter-2.7.5-16.fc20.x86_64 --> Processing Dependency: libtcl8.5.so()(64bit) for package: tkinter-2.7.5-16.fc20.x86_64 --> Processing Dependency: libTix.so()(64bit) for package: tkinter-2.7.5-16.fc20.x86_64 --> Running transaction check ---> Package tcl.x86_64 1:8.5.14-1.fc20 will be installed ---> Package tix.x86_64 1:8.4.3-11.fc20 will be installed ---> Package tk.x86_64 1:8.5.14-1.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: python-easygui noarch 0.96-7.fc20 fedora 481 k Installing for dependencies: python-setuptools noarch 1.4.2-1.fc20 updates 413 k tcl x86_64 1:8.5.14-1.fc20 fedora 1.9 M tix x86_64 1:8.4.3-11.fc20 fedora 253 k tk x86_64 1:8.5.14-1.fc20 fedora 1.4 M tkinter x86_64 2.7.5-16.fc20 updates 316 k Transaction Summary ================================================================================ Install 1 Package (+5 Dependent packages) Total download size: 4.7 M Installed size: 13 M Downloading packages: (1/6): python-setuptools-1.4.2-1.fc20.noarch.rpm | 413 kB 00:00 (2/6): python-easygui-0.96-7.fc20.noarch.rpm | 481 kB 00:00 (3/6): tkinter-2.7.5-16.fc20.x86_64.rpm | 316 kB 00:00 (4/6): tix-8.4.3-11.fc20.x86_64.rpm | 253 kB 00:01 (5/6): tcl-8.5.14-1.fc20.x86_64.rpm | 1.9 MB 00:01 (6/6): tk-8.5.14-1.fc20.x86_64.rpm | 1.4 MB 00:03 -------------------------------------------------------------------------------- Total 1.5 MB/s | 4.7 MB 00:03 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : 1:tcl-8.5.14-1.fc20.x86_64 1/6 Installing : 1:tk-8.5.14-1.fc20.x86_64 2/6 Installing : 1:tix-8.4.3-11.fc20.x86_64 3/6 Installing : tkinter-2.7.5-16.fc20.x86_64 4/6 Installing : python-setuptools-1.4.2-1.fc20.noarch 5/6 Installing : python-easygui-0.96-7.fc20.noarch 6/6 Verifying : 1:tk-8.5.14-1.fc20.x86_64 1/6 Verifying : tkinter-2.7.5-16.fc20.x86_64 2/6 Verifying : 1:tix-8.4.3-11.fc20.x86_64 3/6 Verifying : 1:tcl-8.5.14-1.fc20.x86_64 4/6 Verifying : python-easygui-0.96-7.fc20.noarch 5/6 Verifying : python-setuptools-1.4.2-1.fc20.noarch 6/6 Installed: python-easygui.noarch 0:0.96-7.fc20 Dependency Installed: python-setuptools.noarch 0:1.4.2-1.fc20 tcl.x86_64 1:8.5.14-1.fc20 tix.x86_64 1:8.4.3-11.fc20 tk.x86_64 1:8.5.14-1.fc20 tkinter.x86_64 0:2.7.5-16.fc20 Complete! |
You can then test the EasyGUI library with the following three lines of code inside the IDLE interpreter:
Python 2.7.5 (default, Apr 10 2015, 08:09:05) [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import easygui >>> flavor = easygui.enterbox("What flavor of bum do you like?") >>> if easygui.msgbox("You like " + flavor + " gum.") == 'OK': ... print "OK button clicked ..." ... OK button clicked ... |
The easygui.enterbox call displays the image below. Enter “Peppermint” in the entry box and click the OK button to assign the “Peppermint” string literal to the flavor variable.
The easygui.msgbox call displays the message below:
When you click the OK button, the program returns an “OK” string to the Python code. It prints the string “OK button clicked …” string:
As always, I hope this helps those looking for instructions and a quick way to play with Python and GUI applications.
Reset Oracle Password
This blog entry shows you how to reset the system password for an Oracle Database. It uses a Linux image running Oracle Database 11g Express Edition. It assumes the student user is the sudoer user.
After you sign on to the student user account, you open a Terminal session and you should see the following:
[student@localhost python]$ |
The oracle user account should be configured to prevent a login. So, you should use the su command or sudo command to open a terminal shell as the root user.
[student@localhost python]$ sudo sh [sudo] password for student: |
As the root user, you can login as the oracle user with the following command:
su - oracle |
and, you should see the following prompt. You can see the present working directory (pwd) with the pwd command:
-bash-4.2$ pwd /u01/app/oracle |
You need to source the oracle_env.sh shell file created by the installation of the Oracle Database during the installation. You have two approaches to source the environment file, the first approach is with a dot (.), like
. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh |
or, this
source /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh |
The oracle_env.sh file contains the following:
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe export ORACLE_SID=XE export NLS_LANG=`$ORACLE_HOME/bin/nls_lang.sh` export PATH=$ORACLE_HOME/bin:$PATH |
Now, you can connect to the Oracle Database as the internal user with the following command:
sqlplus / as sysdba |
Once connected as the internal user, you can reset the system user’s password to “cangetin” with this command:
ALTER USER system IDENTIFIED BY cangetin; |
At this point, you can also stop and start the database. You stop the database with this command:
shutdown immediate |
You can then start the database with this command:
startup |
After setting the system user password, sign out of SQL*Plus. Then, you can type two exits to return to the student user account, like this:
-bash-4.2$ exit logout sh-4.2# exit exit [student@localhost python]$ |
As always, I hope this helps those who need to reset the system password when they don’t know what it was to begin with.
Oracle Diagnostic Queries
It’s always a challenge when you want to build your own Oracle SQL Tools. I was asked how you could synchronize multiple cursors into a single source. The answer is quite simple, you write an Oracle object type to represent a record structure, an Oracle list of the record structure, and a stored function to return the list of the record structure.
For this example, you create the following table_struct object type and a table_list collection type:
/* Drop the types from most to least dependent. */ DROP TYPE table_list; DROP TYPE table_struct; /* Create the record type structure. */ CREATE OR REPLACE TYPE table_struct IS OBJECT ( table_name VARCHAR2(30) , column_cnt NUMBER , row_cnt NUMBER ); / /* Create the collection of a record type structure. */ CREATE OR REPLACE TYPE table_list IS TABLE OF table_struct; / |
The following listing function now reads all table names from the user_tables view. A subordinate cursor reads the user_tab_columns view for the number of columns in a table. A Native Dynamic SQL (NDS) cursor counts the number of rows in each tables found in the .
/* Create the listing function. */
CREATE OR REPLACE
FUNCTION listing RETURN table_list IS
/* Variable list. */
lv_column_cnt NUMBER;
lv_row_cnt NUMBER;
/* Declare a statement variable. */
stmt VARCHAR2(200);
/* Declare a system reference cursor variable. */
lv_refcursor SYS_REFCURSOR;
lv_table_cnt NUMBER;
/* Declare an output variable. */
lv_list TABLE_LIST := table_list();
/* Declare a table list cursor that excludes APEX tables. */
CURSOR c IS
SELECT table_name
FROM user_tables
WHERE table_name NOT IN
('DEPT','EMP','APEX$_ACL','APEX$_WS_WEBPG_SECTIONS','APEX$_WS_ROWS'
,'APEX$_WS_HISTORY','APEX$_WS_NOTES','APEX$_WS_LINKS'
,'APEX$_WS_TAGS','APEX$_WS_FILES','APEX$_WS_WEBPG_SECTION_HISTORY'
,'DEMO_USERS','DEMO_CUSTOMERS','DEMO_ORDERS','DEMO_PRODUCT_INFO'
,'DEMO_ORDER_ITEMS','DEMO_STATES');
/* Declare a column count. */
CURSOR cnt
( cv_table_name VARCHAR2 ) IS
SELECT table_name
, COUNT(column_id) AS cnt_columns
FROM user_tab_columns
WHERE table_name = cv_table_name
GROUP BY table_name;
BEGIN
/* Read through the data set of non-environment variables. */
FOR i IN c LOOP
/* Count the columns of a table. */
FOR j IN cnt(i.table_name) LOOP
lv_column_cnt := j.cnt_columns;
END LOOP;
/* Declare a statement. */
stmt := 'SELECT COUNT(*) AS column_cnt FROM '||i.table_name;
/* Open the cursor and write set to collection. */
OPEN lv_refcursor FOR stmt;
LOOP
FETCH lv_refcursor INTO lv_table_cnt;
EXIT WHEN lv_refcursor%NOTFOUND;
lv_list.EXTEND;
lv_list(lv_list.COUNT) := table_struct(
table_name => i.table_name
, column_cnt => lv_column_cnt
, row_cnt => lv_table_cnt );
END LOOP;
END LOOP;
RETURN lv_list;
END;
/ |
The following query pulls the processed data set as the function’s result:
COL table_name FORMAT A20 HEADING "Table Name" COL column_cnt FORMAT 9,999 HEADING "Column #" COL row_cnt FORMAT 9,999 HEADING "Row #" SELECT table_name , column_cnt , row_cnt FROM TABLE(listing); |
It returns the following result set:
Table Name Column # Row # -------------------- -------- ------ SYSTEM_USER 11 5 COMMON_LOOKUP 10 49 MEMBER 9 10 CONTACT 10 18 ADDRESS 10 18 STREET_ADDRESS 8 28 TELEPHONE 11 18 RENTAL 8 4,694 ITEM 14 93 RENTAL_ITEM 9 4,703 PRICE 11 558 TRANSACTION 12 4,694 CALENDAR 9 300 AIRPORT 9 6 ACCOUNT_LIST 8 200 15 rows selected. |
As always, I hope this helps those trying to work with the Oracle database.
Basic Python Object
One of my students wanted a quick example of a Python object with getters and setters. So, I wrote a little example that I’ll share.
You define this file in a physical directory that is in your $PYTHONPATH, like this:
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 | # Define Coordinate class. class Coordinate: # The method that initializes the Coordinate class. def __init__ (self, x, y): self.x = x self.y = y # Gets the x value from the instance. def getX (self): return self.x # Gets the y value from the instance. def getY (self): return self.y # Sets the x value in the instance. def setX (self, x): self.x = x # Sets the y value in the instance. def setY (self, y): self.y = y # Prints the coordinate pair. def printCoordinate(self): print (self.x, self.y) |
Assuming the file name is Coordinate.py, you can put it into the Python Idle environment with the following command:
from Coordinate import Coordinate |
You initialize the class, like this:
g = Coordinate(49,49) |
Then, you can access the variables of the class or it’s methods as shown below:
# Print the retrieved value of x from the g instance of the Coordinate class. print g.getX() # Print the formatted and retrieved value of x from the g instance of the Coordinate class. print "[" + str(g.getX()) + "]" # Set the value of x inside the g instance of the Coordinate class. print g.setX(39) # Print the Coordinates as a set. g.printCoordinate() |
You would see the following results:
49 [49] (39,49) |
As always, I hope that helps those looking for a solution.
Create a Python Module
Sometime formal programming documentation is less than clear. At least, it’s less than clear until you’ve written your first solution. The Modules section of the Python language is one of those that takes a few moments to digest.
Chapters 22 and 23 in Learning Python gives some additional details but not a clear step-by-step approach to implementing Python modules. This post is designed to present the steps to write, import, and call a Python module. I figured that it would be helpful to write one for my students, and posting it in the blog seemed like the best idea.
I wrote the module to parse an Oracle version string into what we’d commonly expect to see, like the release number, an “R”, a release version, and then the full version number. The module name is more or less equivalent to a package name, and the file name is effectively the module name. The file name is strVersionOracle.py, which makes the strVersionOracle the module name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # Parse and format Oracle version. def formatVersion(s): # Split string into collection. list = s.split(".") # Iterate through the result set. for i, l in enumerate(list): if i == 0 and list[i] == "11": label = str(l) + "g" elif i == 0 and list[i] == "12": label = label + str(l) + "c" elif i == 1: label = label + "R" + list[i] + " (" + s + ")" # Return the formatted string. return label |
You can put this in any directory as long as you add it to the Python path. There are two Python paths to maintain. One is in the file system and the other is in Python’s interactive IDLE environment. You can check the contents of the IDLE path with the following interactive commands:
import sys print sys.path |
It prints the following:
['', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages'] |
You can append to the IDLE path using the following command:
sys.path.append("/home/student/Code/python") |
After putting the module in the runtime path, you can test the code in the IDLE environment:
1 2 3 | import cx_Oracle db = cx_Oracle.connect("student/student@xe") print strVersionOracle.formatVersion(db.version) |
Line 3 prints the result by calling the formatVersion function inside the strVersionOracle module. It prints the following:
11gR2 (11.2.0.2.0) |
You can test the program outside of the runtime environment with the following oracleConnection.py file. It runs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # Import the Oracle library. import cx_Oracle import strVersionOracle try: # Create a connection. db = cx_Oracle.connect("student/student@xe") # Print a message. print "Connected to the Oracle " + strVersionOracle.formatVersion(db.version) + " database." except cx_Oracle.DatabaseError, 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() |
You can call the formatVersion() function rather than a combination of module and function names when you write a more qualified import statement on line 3, like:
3 | from strVersionOracle import formatVersion |
Then, you can call the formatVersion() function like this on line 10:
10 | print "Connected to the Oracle " + formatVersion(db.version) + " database." |
It works because you told it to import a function from a Python module. The first example imports a module that may contain one to many functions, and that style requires you to qualify the location of functions inside imported modules.
The oracleConnection.py program works when you call it from the Bash shell provided you do so from the same directory where the oracleConnection.py and strVersionOracle.py files (or Python modules) are located. If you call the oracleConnection.py file from a different directory, the reference to the library raises the following error:
Traceback (most recent call last): File "oracleConnection.py", line 3, in <module> import strVersionOracle ImportError: No module named strVersionOracle |
You can fix this error by adding the directory where the strVersionOracle.py file exists, like
export set PYTHONPATH=/home/student/Code/python |
Then, you can call successfully the oracleConnection.py file from any directory:
python oracleConnection.py |
The program will connect to the Oracle database as the student user, and print the following message to the console:
Connected to the Oracle 11gR2 (11.2.0.2.0) database. |
I hope this helps those trying to create and use Python modules.
Python for loops
It’s always interesting to explain a new programming language to students. Python does presents some challenges to that learning process. I think for-loops can be a bit of a challenge until you understand them. Many students are most familiar with the traditional for loop like Java:
for (i = 0; i < 5; i++) { ... } |
Python supports three types of for-loops – a range for loop, a for-each expression, and a for-loop with enumeration. Below are examples of each of these loops.
- A range for-loop goes from a low numerical value to a high numerical value, like:
for i in range(0,3): print i |
It prints the following range values:
0 1 2 |
- A for-each loop goes from the first to the last item while ignoring indexes, like:
list = ['a','b','c'] for i in list: print i |
It prints the following elements of the list:
a b c |
- A for-loop with enumeration goes from the first to the last item while ignoring indexes, like:
list = ['a','b','c'] for i, e in enumerate(list): print "[" + str(i) + "][" + list[i] + "]" |
The i represents the index values and the e represents the elements of a list. The str() function casts the numeric value to a string.
It prints the following:
[0][a] [1][b] [2][c] |
This should help my students and I hope it helps you if you’re trying to sort out how to use for loops in Python.
Install cx_Oracle for Python
This shows you how to install the cx_Oracle library for Python 2.7 on Fedora Linux. If Fedora has it on the server you can download it with the following yum command:
yum install -y cx_Oracle-5.2.1-11g-py27-1.x86_64.rpm |
Currently, you’ll get the following failure because it’s not available in the Fedora repository:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00:00 mysql-tools-community | 2.5 kB 00:00:00 mysql56-community | 2.5 kB 00:00:00 pgdg93 | 3.6 kB 00:00:00 updates/20/x86_64/metalink | 2.3 kB 00:00:00 No package cx_Oracle-5.2.1-11g-py27-1.x86_64.rpm available. Error: Nothing to do |
You can download the cx_Oracle library from the Python web site. The cx_Oracle documentation qualifies module interfaces, objects, and connections. Assuming your Linux user’s name is student, you download the cx_Oracle library into the /home/student/Downloads directory. Then, you use the su or sudo command to become the root user.
As the root user, run the following yum command:
yum install -y ~student/Downloads/cx_Oracle-5.2.1-11g-py27-1.x86_64.rpm |
You should see the following output:
Loaded plugins: langpacks, refresh-packagekit Examining /home/student/Downloads/cx_Oracle-5.2.1-11g-py27-1.x86_64.rpm: cx_Oracle-5.2.1-1.x86_64 Marking /home/student/Downloads/cx_Oracle-5.2.1-11g-py27-1.x86_64.rpm to be installed Resolving Dependencies --> Running transaction check ---> Package cx_Oracle.x86_64 0:5.2.1-1 will be installed --> Finished Dependency Resolution Dependencies Resolved ======================================================================================= Package Arch Version Repository Size ======================================================================================= Installing: cx_Oracle x86_64 5.2.1-1 /cx_Oracle-5.2.1-11g-py27-1.x86_64 717 k Transaction Summary ======================================================================================= Install 1 Package Total size: 717 k Installed size: 717 k Downloading packages: Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : cx_Oracle-5.2.1-1.x86_64 1/1 Verifying : cx_Oracle-5.2.1-1.x86_64 1/1 Installed: cx_Oracle.x86_64 0:5.2.1-1 Complete! |
After you install the cx_Oracle-5.2.1-1.x86_64 package, you can find the installed files with this rpm command:
rpm -ql cx_Oracle-5.2.1-1.x86_64 |
It lists:
/usr/lib64/python2.7/site-packages/cx_Oracle-5.2.1-py2.7.egg-info /usr/lib64/python2.7/site-packages/cx_Oracle-5.2.1-py2.7.egg-info/PKG-INFO /usr/lib64/python2.7/site-packages/cx_Oracle-5.2.1-py2.7.egg-info/SOURCES.txt /usr/lib64/python2.7/site-packages/cx_Oracle-5.2.1-py2.7.egg-info/dependency_links.txt /usr/lib64/python2.7/site-packages/cx_Oracle-5.2.1-py2.7.egg-info/top_level.txt /usr/lib64/python2.7/site-packages/cx_Oracle.so /usr/share/doc/cx_Oracle-5.2.1 /usr/share/doc/cx_Oracle-5.2.1/BUILD.txt /usr/share/doc/cx_Oracle-5.2.1/README.txt /usr/share/doc/cx_Oracle-5.2.1/samples /usr/share/doc/cx_Oracle-5.2.1/samples/DatabaseChangeNotification.py /usr/share/doc/cx_Oracle-5.2.1/samples/DatabaseShutdown.py /usr/share/doc/cx_Oracle-5.2.1/samples/DatabaseStartup.py /usr/share/doc/cx_Oracle-5.2.1/samples/ReturnLongs.py /usr/share/doc/cx_Oracle-5.2.1/samples/ReturnUnicode.py /usr/share/doc/cx_Oracle-5.2.1/samples/RowsAsInstance.py /usr/share/doc/cx_Oracle-5.2.1/test /usr/share/doc/cx_Oracle-5.2.1/test/3kArrayDMLBatchError.py /usr/share/doc/cx_Oracle-5.2.1/test/3kNumberVar.py /usr/share/doc/cx_Oracle-5.2.1/test/3kStringVar.py /usr/share/doc/cx_Oracle-5.2.1/test/ArrayDMLBatchError.py /usr/share/doc/cx_Oracle-5.2.1/test/BooleanVar.py /usr/share/doc/cx_Oracle-5.2.1/test/Connection.py /usr/share/doc/cx_Oracle-5.2.1/test/Cursor.py /usr/share/doc/cx_Oracle-5.2.1/test/CursorVar.py /usr/share/doc/cx_Oracle-5.2.1/test/DateTimeVar.py /usr/share/doc/cx_Oracle-5.2.1/test/IntervalVar.py /usr/share/doc/cx_Oracle-5.2.1/test/LobVar.py /usr/share/doc/cx_Oracle-5.2.1/test/LongVar.py /usr/share/doc/cx_Oracle-5.2.1/test/NCharVar.py /usr/share/doc/cx_Oracle-5.2.1/test/NumberVar.py /usr/share/doc/cx_Oracle-5.2.1/test/ObjectVar.py /usr/share/doc/cx_Oracle-5.2.1/test/SessionPool.py /usr/share/doc/cx_Oracle-5.2.1/test/SetupTest.sql /usr/share/doc/cx_Oracle-5.2.1/test/StringVar.py /usr/share/doc/cx_Oracle-5.2.1/test/TestEnv.py /usr/share/doc/cx_Oracle-5.2.1/test/TimestampVar.py /usr/share/doc/cx_Oracle-5.2.1/test/test.py /usr/share/doc/cx_Oracle-5.2.1/test/test3k.py /usr/share/doc/cx_Oracle-5.2.1/test/test_dbapi20.py /usr/share/doc/cx_Oracle-5.2.1/test/uArrayDMLBatchError.py /usr/share/doc/cx_Oracle-5.2.1/test/uConnection.py /usr/share/doc/cx_Oracle-5.2.1/test/uCursor.py /usr/share/doc/cx_Oracle-5.2.1/test/uCursorVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uDateTimeVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uIntervalVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uLobVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uLongVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uNumberVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uObjectVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uSessionPool.py /usr/share/doc/cx_Oracle-5.2.1/test/uStringVar.py /usr/share/doc/cx_Oracle-5.2.1/test/uTimestampVar.py |
After you installed the software, you can test whether inside Python’s IDLE environment with the import command, like this:
Python 2.7.5 (default, Apr 10 2015, 08:09:05) [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import cx_Oracle Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: libclntsh.so.11.1: cannot open shared object file: No such file or directory |
This error indicates that Oracle Client software isn’t installed, which is true in this case. I only installed the Oracle Database 11g Express Edition. You need to download the Oracle Client software and install it as the root user.
You download the Oracle Client software from the Oracle web site. Assuming your Linux user’s name is student, you download the cx_Oracle library into the /home/student/Downloads directory. Then, you use the su or sudo command to become the root user.
As the root user, run the following yum command:
yum install -y ~student/Downloads/oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm |
You should see the following output:
Loaded plugins: langpacks, refresh-packagekit
Examining /home/student/Downloads/oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm: oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64
Marking /home/student/Downloads/oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package oracle-instantclient11.2-basic.x86_64 0:11.2.0.4.0-1 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package
Arch Version
Repository Size
================================================================================
Installing:
oracle-instantclient11.2-basic
x86_64 11.2.0.4.0-1
/oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64 179 M
Transaction Summary
================================================================================
Install 1 Package
Total size: 179 M
Installed size: 179 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
Installing : oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64 1/1
Verifying : oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64 1/1
Installed:
oracle-instantclient11.2-basic.x86_64 0:11.2.0.4.0-1
Complete! |
You can create a Python program that checks your ability to connect to the Oracle database, like the following oracleConnection.py file:
# Import the Oracle library. import cx_Oracle try: # Create a connection. db = cx_Oracle.connect("student/student@xe") # Print a message. print "Connected to the Oracle " + db.version + " database." except cx_Oracle.DatabaseError, e: error, = e.args print >> sys.stderr, "Oracle-Error-Code:", error.code print >> sys.stderr, "Oracle-Error-Message:", error.message finally: # Close cursor. db.close() |
You can run this from the Linux command line with the following syntax:
python oracleConnection.py |
It should return the following string:
Connected to the Oracle 11.2.0.2.0 database. |
Now, you can create a Python program that reads data from the Oracle database. The following oracleString.py file reads a string literal from the pseudo table dual:
# Import the Oracle library. import cx_Oracle try: # Create a connection. db = cx_Oracle.connect("student/student@xe") # Create a cursor. cursor = db.cursor() # Execute a query. cursor.execute("SELECT 'Hello world!' FROM dual") # Read the contents of the cursor. for row in cursor: print (row[0]) except cx_Oracle.DatabaseError, 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() |
You can run this from the Linux command line with the following syntax:
python oracleString.py |
It should return the following string:
Hello world! |
Now, you can create a Python program that reads actual table data from the Oracle database (assuming you have a copy of my video store database). The following oracleTable.py file reads a string literal from the pseudo table dual:
# Import the Oracle library. import cx_Oracle try: # Create a connection. db = cx_Oracle.connect("student/student@xe") # Create a cursor. cursor = db.cursor() # Execute a query. cursor.execute("SELECT item_title, item_subtitle FROM item") # Read the contents of the cursor. for row in cursor: print (row[0], row[1]) except cx_Oracle.DatabaseError, 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() |
You can run this from the Linux command line with the following syntax:
python oracleTable.py |
It should return the following strings (only a subset of the returned values):
("Harry Potter and the Sorcer's Stone", 'Two-Disc Special Edition')
('Harry Potter and the Chamber of Secrets', 'Two-Disc Special Edition')
('Harry Potter and the Prisoner of Azkaban', 'Two-Disc Special Edition')
('Harry Potter and the Chamber of Secrets', None)
('Harry Potter and the Goblet of Fire', 'Widescreen Edition')
('Harry Potter and the Goblet of Fire', 'Two-Disc Special Edition')
('Harry Potter and the Order of the Phoenix', 'Widescreen Edition')
('The Lord of the Rings - Fellowship of the Ring', 'Widescreen Edition')
('The Lord of the Rings - Fellowship of the Ring', 'Platinum Series Special Extended Edition')
('The Lord of the Rings - Two Towers', 'Widescreen Edition')
('The Lord of the Rings - Two Towers', 'Platinum Series Special Extended Edition')
('The Lord of the Rings - The Return of the King', 'Widescreen Edition')
('The Lord of the Rings - The Return of the King', 'Platinum Series Special Extended Edition')
('Star Wars - Episode I', 'The Phantom Menace')
('Star Wars - Episode II', 'Attack of the Clones')
('Star Wars - Episode III', 'Revenge of the Sith')
('Star Wars - Episode IV', 'A New Hope')
('Star Wars - Episode V', 'The Empire Strikes Back')
('Star Wars - Episode VI', 'Return of the Jedi') |
As always, I hope this helps others who want to work with Python and the Oracle database.
Oracle Segment Fails
The instance that I’ve built for my students in a Fedora VM is quite stable except for one feature. The feature is the hibernation process of the base operating system. Sometimes when the base operating system hibernates, it causes the Oracle shared memory segment to fail. When that happens you get the following error:
ERROR: ORA-01034: ORACLE NOT available ORA-27101: shared memory realm does NOT exist Linux-x86_64 Error: 2: No such FILE OR DIRECTORY Process ID: 0 SESSION ID: 0 Serial NUMBER: 0 |
I created the master sudoer account as the student user. The oracle user is configured so that you can’t log in to the Linux OS with it. To restart the instance you can do the following in a default Oracle 11g XE installation:
su - root |
or, you can do this:
sudo sh |
Then as the root user, you can sign on to the oracle user’s account by using the su command without a password, like:
su - oracle |
As the user who installed the Oracle instance, you can connect to the database without a password after you source the environment file. The standard Oracle 11g XE environment file can be sources like this:
. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh |
Alternatively, for my students there is a .bashrc file that they can manually source. It contains the following:
# Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions . /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh # Wrap sqlplus with rlwrap to edit prior lines with the # up, down, left and right keys. 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 } # Set vi as a command line editor. set -o vi |
You can source the oracle user’s .bashrc account, like this:
. .bashrc |
After you’ve sourced the environment, you can connect as the internal user with the following syntax:
sqlplus / AS sysdba |
Connected as the internal user, run these two commands in sequence:
shutdown IMMEDIATE
startup |
Then, you should be able to connect as the student user or another ordinary user with the following syntax:
CONNECT student/student |
Hope this helps my students and those who want to know how to restart the Oracle instance.
Multitenant Architecture 12c
I thought this illustration was an interesting view of Oracle Database 12c’s Multitenant Architecture. It posted on ToadWorld.com today in a new article by Deiby Gomez and I thought it might be interesting for others.
You can see how to provision a pluggable database in this article on provisioning a pluggable database. As always, I hope it helps.
OpenWorld/JavaOne
Brendan also gave me a copy of the group effort on Real World SQL and PL/SQL: Advice from the Experts. I looked through it too, but as is often the case with 5 or more author’s, it looks a little mixed. I liked the section on Advanced Analytics (Chapters 10 & 11), and thought Chapter 12 has some good points on encryption.
While there were rumors about Oracle Database 13, they’re more or less just that. The funniest was it’ll be a short release, and eclipsed by Oracle Database 14 because of superstition. If that were true, Oracle might just re-market like Oracle 2 Version 1. In short, I think we’ll need to wait to hear about the next version next year.
In case you’re wondering, the Giants lost to St Louis. The score was 3-0. It was also 87° in San Francisco yesterday.



