Archive for the ‘Python 3.x’ Category
pgAdmin4 on Fedora 30
While attempting an install of pgAdmin and updating a Fedora 30 environment, I encountered a conflict on the upgrade of MySQL 8.0.17-1 to 8.0.17.2. The community-mysql-8.0.17-2.fc30.x86_64
had conflicts with:
mysql-community-client-8.0.17-1.fc30.x86_64
packagemysql-community-server-8.0.17-1.fc30.x86_64
package
I tried to update the system before install pgadmin4
with the following syntax:
dnf -y update && dnf -y install pgadmin4 |
The dnf
utility raise the following MySQL package errors during transaction checking:
Display detailed console log →
Error: Transaction check error: file /usr/bin/mysql conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysql_config_editor conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqladmin conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlbinlog conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlcheck conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqldump conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlimport conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlpump conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlshow conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/mysqlslap conflicts between attempted installs of community-mysql-8.0.17-2.fc30.x86_64 and mysql-community-client-8.0.17-1.fc30.x86_64 file /usr/bin/ibd2sdi conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/innochecksum conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/my_print_defaults conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/myisam_ftdump conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/myisamchk conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/myisamlog conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/myisampack conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/mysql_secure_installation conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/mysql_ssl_rsa_setup conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/mysql_tzinfo_to_sql conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/mysql_upgrade conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/mysqld_pre_systemd conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/bin/perror conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib/systemd/system/mysqld.service conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib/systemd/system/mysqld@.service conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/adt_null.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/auth_socket.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/component_audit_api_message_emit.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/component_log_filter_dragnet.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/component_log_sink_json.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/component_log_sink_syseventlog.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/component_validate_password.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/connection_control.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/ddl_rewriter.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/group_replication.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/ha_example.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/ha_mock.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/innodb_engine.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/keyring_file.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/keyring_udf.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/libmemcached.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/locking_service.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/mypluglib.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/mysql_clone.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/mysql_no_login.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/rewrite_example.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/rewriter.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/semisync_master.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/semisync_slave.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/validate_password.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/plugin/version_token.so conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/sbin/mysqld conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /var/lib/mysql conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /var/lib/mysql-keyring conflicts between attempted installs of community-mysql-server-8.0.17-2.fc30.x86_64 and mysql-community-server-8.0.17-1.fc30.x86_64 file /usr/lib64/mysql/libmysqlclient.so.21.1.17 conflicts between attempted installs of community-mysql-libs-8.0.17-2.fc30.x86_64 and mysql-community-libs-8.0.17-1.fc30.x86_64 |
Since I’m not sure what’s wrong or how to fix it, I’ve put it in my queue of things to get to later. However, when I figure it out I’ll update this blog page with the solution or work around. If anybody knows the fix and would like to share, please let me know.
I removed the pending update packages with the following command:
dnf clean packages |
Then, I simply installed pgadmin4
with the following command:
dnf -y install pgadmin4 |
Display detailed console log →
The pgadmin4
configuration instructions can be found for several Linux versions at Josphat Mutai’s Computing for Geeks web page. On Fedora 30, you need to do the following:
- Install, start, and enable Apache as the
httpd
service unless you already have done that. - Copy the
/etc/httpd/conf.d/pgadmin4.conf.sample
file to/etc/httpd/conf.d/pgadmin4.conf
, which is a new file. - Restart the
httpd
service to incorporate thepgadmin4
configuration file.
After that, you create the following new directories as the root
or sudo
user:
/var/lib/pgadmin4
/var/log/pgadmin4
You can make both directories with a single mkdir
command, like:
mkdir -p /var/lib/pgadmin4 /var/log/pgadmin4 |
As the root
or sudo
user, change the ownership of these two directories to the apache
user with the following syntax:
chown -R apache:apache /var/lib/pgadmin4 /var/log/pgadmin4 |
You add the following four statements to the config_distro.py
file in the /usr/lib/python3.7/site-packages/pgadmin4-web
directory as the root
or sudo
user:
LOG_FILE = '/var/log/pgadmin4/pgadmin4.log' SQLITE_PATH = '/var/lib/pgadmin4/pgadmin4.db' SESSION_DB_PATH = '/var/lib/pgadmin4/sessions' STORAGE_DIR = '/var/lib/pgadmin4/storage' |
You need to setup the pgadmin user with the following python3 command:
python3 /usr/lib/python3.7/site-packages/pgadmin4-web/setup.py |
Enter the following values, a real email address and a password twice:
NOTE: Configuring authentication for SERVER mode. Enter the email address and password to use for the initial pgAdmin user account: Email address: admin@example.com Password: your_password Retype password: your_password pgAdmin 4 - Application Initialisation ====================================== |
Assuming you have an enabled firewall, you need to issue the following two commands as the root
or sudo
user:
rirewall-cmd --permanent --add-service=http firewall-cmd --reload |
You invoke pgAdmin4 from within a browser window with the following URL for a stand alone workstation (for a workstation on a DNS network you would enter pgadmin.domain.domain_type
in lieu of localhost):
pgadmin/localhost/pgadmin4 |
You most likely will encounter an Internal Server Error, the recommended fix is reputed to be:
ausearch -c 'httpd' --raw | audit2allow -M my-httpd semodule -X 300 -i my-httpd.pp |
It didn’t work for me. At the end of the process, I have an Internal Server Error. It is something that I’ll try to fix next. The actual error message:
Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request. Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error. More information about this error may be available in the server error log. |
If somebody figures out the last step before I do, that’s great. Let me and everybody else know the mystery.
On a positive note, the pgadmin4 package provided the psycopg2
library. I had looked for it as a psycopg2
package but it is in python3-psycopg2
package.
Django on Fedora 30
It seemed opportune to add Django to the Fedora 30 instance that I build and maintain for my students. Here are the instructions, which I developed with the prior Fedora 28/29 instructions.
- Check your Python3 installation with the following command:
python3 -V
It should return this but if it doesn’t you should install
python3
:Python 3.7.4
- Check whether
pip3
is installation by installing it when its not:sudo def -y install python3-php
It should return:
Last metadata expiration check: 0:44:52 ago on Tue 10 Sep 2019 11:02:33 AM MDT. Package python3-pip-19.0.3-3.fc30.noarch is already installed. Dependencies resolved. Nothing to do. Complete!
- Check whether
Django
is installation by installing it when its not withpip3
installation utility:sudo pip3 install --user Django
It should return the following if installed:
Requirement already satisfied: Django in /usr/lib/python3.7/site-packages (2.1.10) Requirement already satisfied: pytz in /usr/lib/python3.7/site-packages (from Django) (2018.5)
- Check your
django-admin
account location with thewhich
utility:which django-admin
It should return the following on Fedora 30 when installed:
/usr/bin/django-admin
- Create a Django test application with the
django-admin
utility by creating a project directory. My directory is a bit deep. For reference, it is:/home/student/Code/python/django/projects
Change to that projects directory, and run the following command:
django-admin startproject test_app
After that command change directory with the
cd
command into thetest_app
subdirectory in yourprojects
directory. Run the manage.py program with the following command:python3 manage.py migrate
You should see the following:
Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK
Next, your would create an admin
account. You’re done.
Python MySQL Query
Somebody asked me how to expand a prior example with the static variables so that it took arguments at the command line for the variables. This example uses Python 3 new features in the datetime
package.
There’s a small trick converting the string
arguments to date
data types. Here’s a quick example that shows you how to convert the argument list into individual date
data type variables:
#!/usr/bin/python3 # include standard modules import sys from datetime import datetime # Capture argument list. fullCmdArguments = sys.argv # Assignable variables. beginDate = "" endDate = "" # Assign argument list to variable. argumentList = fullCmdArguments[1:] # Enumerate through the argument list where beginDate precedes endDate as strings. try: for i, s in enumerate(argumentList): if (i == 0): beginDate = datetime.date(datetime.fromisoformat(s)) elif (i == 1): endDate = datetime.date(datetime.fromisoformat(s)) except ValueError: print("One of the first two arguments is not a valid date (YYYY-MM-DD).") # Print the processed values and types. print("Begin Date: [",beginDate,"][",type(beginDate),"]") print("End Date: [",endDate,"][",type(endDate),"]") |
Assume you call this arguments.py
. Then, you call it with valid conforming date format value like the following command-line example:
./arguments.py 2001-01-01 2003-12-31 |
It returns the arguments after they have been converted to date
data types. The results should look like this:
Begin Date: 1991-01-01 [ <class 'datetime.date'> ] End Date: 2004-12-31 [ <class 'datetime.date'> ] |
The next Python example accepts dynamic arguments at the command line to query the MySQL database:
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 | #!/usr/bin/python3 # Import the library. import sys import mysql.connector from datetime import datetime from datetime import date from mysql.connector import errorcode # Capture argument list. fullCmdArguments = sys.argv # Assignable variables. start_date = "" end_date = "" # Assign argument list to variable. argumentList = fullCmdArguments[1:] # Check and process argument list. # ============================================================ # If there are less than two arguments provide default values. # Else enumerate and convert strings to dates. # ============================================================ if (len(argumentList) < 2): # Set a default start date. if (isinstance(start_date,str)): start_date = date(1980, 1, 1) # Set the default end date. if (isinstance(end_date,str)): end_date = datetime.date(datetime.today()) else: # Enumerate through the argument list where beginDate precedes endDate as strings. try: for i, s in enumerate(argumentList): if (i == 0): start_date = datetime.date(datetime.fromisoformat(s)) elif (i == 1): end_date = datetime.date(datetime.fromisoformat(s)) except ValueError: print("One of the first two arguments is not a valid date (YYYY-MM-DD).") # 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 = ("SELECT CASE " " WHEN item_subtitle IS NULL THEN item_title " " ELSE CONCAT(item_title,': ',item_subtitle) " " END AS title, " "release_date " "FROM item " "WHERE release_date BETWEEN %s AND %s " "ORDER BY item_title") # Execute cursor. cursor.execute(query, (start_date, end_date)) # Display the rows returned by the query. for (item_name, release_date) in cursor: print("{}, {:%d-%b-%Y}".format(item_name, release_date)) # 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. finally: cnx.close() |
You can call the python-mysql-query.py
program with the following syntax:
./python-mysql-query.py 2001-01-01 2003-12-31 |
It returns the films between 1 Jan 2001 and 31 Dec 2003, like this:
Clear and Present Danger: Special Collector's Edition, 06-May-2003 Die Another Day: 2-Disc Ultimate Version, 03-Jun-2003 Die Another Day, 03-Jun-2003 Die Another Day, 03-Jun-2003 Golden Eye, 03-Jun-2003 Golden Eye: Special Edition, 03-Jun-2003 Harry Potter and the Chamber of Secrets, 28-May-2002 Harry Potter and the Chamber of Secrets: Two-Disc Special Edition, 28-May-2002 Harry Potter and the Sorcerer's Stone, 28-May-2002 Harry Potter and the Sorcerer's Stone: Two-Disc Special Edition, 28-May-2002 Harry Potter and the Sorcerer's Stone: Full Screen Edition, 28-May-2002 MarioKart: Double Dash, 17-Nov-2003 Pirates of the Caribbean, 30-Jun-2003 RoboCop, 24-Jul-2003 Splinter Cell: Chaos Theory, 08-Apr-2003 Star Wars II: Attack of the Clones, 16-May-2002 Star Wars II: Attack of the Clones, 16-May-2002 The Chronicles of Narnia: The Lion, the Witch and the Wardrobe, 30-Jun-2003 The Chronicles of Narnia: The Lion, the Witch and the Wardrobe, 16-May-2002 |
As always, I hope this helps somebody who wants to learn how to use Python with the MySQL database.
MySQL Python Connector
While building my student image on Fedora 30, I installed the MySQL PHP Connector (php-mysqlndrp) but neglected to install the Python Connector. This adds the installation and basic test of the Python Connector to the original blog post.
You use the following command with a wildcard as a privileged user. The wildcard is necessary because you need to load two libraries to support Python 2.7 and 3.7, which are installed on Fedora 30. You also need to be the root user or a user that is found in the sudoer’s list:
yum install -y mysql-connector-python* |
Display detailed console log →
Last metadata expiration check: 0:35:46 ago on Tue 20 Aug 2019 05:36:29 PM MDT. Dependencies resolved. ===================================================================================================================================== Package Architecture Version Repository Size ===================================================================================================================================== Installing: mysql-connector-python x86_64 8.0.17-1.fc30 mysql-connectors-community 435 k mysql-connector-python-cext x86_64 8.0.17-1.fc30 mysql-connectors-community 7.7 M mysql-connector-python3 x86_64 8.0.17-1.fc30 mysql-connectors-community 429 k mysql-connector-python3-cext x86_64 8.0.17-1.fc30 mysql-connectors-community 7.7 M Installing dependencies: python2-protobuf noarch 3.6.1-3.fc30 fedora 563 k python3-protobuf noarch 3.6.1-3.fc30 fedora 568 k Transaction Summary ===================================================================================================================================== Install 6 Packages Total download size: 17 M Installed size: 89 M Downloading Packages: (1/6): python3-protobuf-3.6.1-3.fc30.noarch.rpm 1.0 MB/s | 568 kB 00:00 (2/6): python2-protobuf-3.6.1-3.fc30.noarch.rpm 994 kB/s | 563 kB 00:00 (3/6): mysql-connector-python-8.0.17-1.fc30.x86_64.rpm 481 kB/s | 435 kB 00:00 (4/6): mysql-connector-python3-8.0.17-1.fc30.x86_64.rpm 612 kB/s | 429 kB 00:00 (5/6): mysql-connector-python-cext-8.0.17-1.fc30.x86_64.rpm 3.8 MB/s | 7.7 MB 00:02 (6/6): mysql-connector-python3-cext-8.0.17-1.fc30.x86_64.rpm 4.2 MB/s | 7.7 MB 00:01 ------------------------------------------------------------------------------------------------------------------------------------- Total 5.4 MB/s | 17 MB 00:03 warning: /var/cache/dnf/mysql-connectors-community-8bcc2bd350b53f70/packages/mysql-connector-python-8.0.17-1.fc30.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY MySQL Connectors Community 7.0 MB/s | 27 kB 00:00 Importing GPG key 0x5072E1F5: Userid : "MySQL Release Engineering <mysql-build@oss.oracle.com>" Fingerprint: A4A9 4068 76FC BD3C 4567 70C8 8C71 8D3B 5072 E1F5 From : /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql Key imported successfully Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : python3-protobuf-3.6.1-3.fc30.noarch 1/6 Installing : python2-protobuf-3.6.1-3.fc30.noarch 2/6 Installing : mysql-connector-python-8.0.17-1.fc30.x86_64 3/6 Installing : mysql-connector-python3-8.0.17-1.fc30.x86_64 4/6 Installing : mysql-connector-python3-cext-8.0.17-1.fc30.x86_64 5/6 Installing : mysql-connector-python-cext-8.0.17-1.fc30.x86_64 6/6 Running scriptlet: mysql-connector-python-cext-8.0.17-1.fc30.x86_64 6/6 Verifying : python2-protobuf-3.6.1-3.fc30.noarch 1/6 Verifying : python3-protobuf-3.6.1-3.fc30.noarch 2/6 Verifying : mysql-connector-python-8.0.17-1.fc30.x86_64 3/6 Verifying : mysql-connector-python-cext-8.0.17-1.fc30.x86_64 4/6 Verifying : mysql-connector-python3-8.0.17-1.fc30.x86_64 5/6 Verifying : mysql-connector-python3-cext-8.0.17-1.fc30.x86_64 6/6 Installed: mysql-connector-python-8.0.17-1.fc30.x86_64 mysql-connector-python-cext-8.0.17-1.fc30.x86_64 mysql-connector-python3-8.0.17-1.fc30.x86_64 mysql-connector-python3-cext-8.0.17-1.fc30.x86_64 python2-protobuf-3.6.1-3.fc30.noarch python3-protobuf-3.6.1-3.fc30.noarch Complete! |
Leveraging the MySQL Connector/Python Coding Examples documentation, Section 5.1 Connecting to MySQL Using Connector/Python here’s a test of the connection to MySQL 8.
# Import the library. import mysql.connector from mysql.connector import errorcode try: # Open connection. cnx = mysql.connector.connect(user='student', password='student', host='127.0.0.1', database='studentdb') # 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() |
Leveraging the MySQL Connector/Python Coding Examples documentation, Section 5.4 Querying Data Using Connector/Python here’s a test of the connection to MySQL 8.
# Import the library. import datetime import mysql.connector from mysql.connector import errorcode 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 = ("SELECT " "CASE " " WHEN item_subtitle IS NULL THEN item_title " " ELSE CONCAT(item_title,': ',item_subtitle) " "END AS title, " "release_date " "FROM item " "WHERE release_date BETWEEN %s AND %s " "ORDER BY item_title") # Set the start and end date. start_date = datetime.date(1991, 1, 1) end_date = datetime.date(2004, 12, 31) # Execute cursor. cursor.execute(query, (start_date, end_date)) # Display the rows returned by the query. for (item_name, release_date) in cursor: print("{}, {:%d %b %Y}".format(item_name, release_date)) # 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() |
If you run the above in Python 2.7 it works fine. It fails to parse successfully in Python 3.x because the print()
function requires the parentheses all the time. You would need to re-write the except
block, like this with the parentheses:
# 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 |
While it works without the parentheses in Python 2.7, it also works with the parentheses. That means the best practice is to write cross compatible code by always using the parentheses with the print()
function.
As always, I hope this helps somebody.j
Read list of a dictionaries
My students wanted a quick example of how to read a list of a dictionaries in Python. So, here it is:
#!/usr/bin/python # Declare list of dictionaries. cakes = [{'cake':"vanilla",'frosting':"chocolate"} ,{'cake':"chocolate",'frosting':"vanilla"}] # Read the list of dictionaries. for lkey, lvalue in enumerate(cakes): print lvalue['cake'] + " with " + lvalue['frosting'] + " frosting." |
Naturally, a list can contain many things and you should ensure each value you read is a dictionary before trying to read it as a dictionary. At least, I’d suggest you check.
Hope this answers the how.
Installing PIP for Python
If you’re on a Mac running macOS Sierra, you can install PIP to add packages. PIP stands for either of the following:
- PIP installs Packages
- PIP installs Python
You use the following to install the PIP utility:
sudo easy_install pip |
It should return the following:
Searching for pip Reading https://pypi.python.org/simple/pip/ Best match: pip 9.0.1 Downloading https://pypi.python.org/packages/11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/pip-9.0.1.tar.gz#md5=35f01da33009719497f01a4ba69d63c9 Processing pip-9.0.1.tar.gz Writing /tmp/easy_install-ryxjDg/pip-9.0.1/setup.cfg Running pip-9.0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-ryxjDg/pip-9.0.1/egg-dist-tmp-l6_Jjt /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'python_requires' warnings.warn(msg) warning: no previously-included files found matching '.coveragerc' warning: no previously-included files found matching '.mailmap' warning: no previously-included files found matching '.travis.yml' warning: no previously-included files found matching '.landscape.yml' warning: no previously-included files found matching 'pip/_vendor/Makefile' warning: no previously-included files found matching 'tox.ini' warning: no previously-included files found matching 'dev-requirements.txt' warning: no previously-included files found matching 'appveyor.yml' no previously-included directories found matching '.github' no previously-included directories found matching '.travis' no previously-included directories found matching 'docs/_build' no previously-included directories found matching 'contrib' no previously-included directories found matching 'tasks' no previously-included directories found matching 'tests' creating /Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg Extracting pip-9.0.1-py2.7.egg to /Library/Python/2.7/site-packages Adding pip 9.0.1 to easy-install.pth file Installing pip script to /usr/local/bin Installing pip2.7 script to /usr/local/bin Installing pip2 script to /usr/local/bin Installed /Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg Processing dependencies for pip Finished processing dependencies for pip |
After you install PIP, you can use PIP to add custom packages to the Python environment. The
sudo pip install easygui |
You get the following warning and installation:
The directory '/Users/michaelmclaughlin/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag. The directory '/Users/michaelmclaughlin/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag. Collecting easygui Downloading easygui-0.98.1-py2.py3-none-any.whl (90kB) 100% |████████████████████████████████| 92kB 1.0MB/s Installing collected packages: easygui Successfully installed easygui-0.98.1 |
After installing the easygui
Python library, you can change to the root
directory to confirm the installation of the easygui
Python library with the following command:
find . -name easygui* 2>/dev/null |
It returns the following:
./Library/Python/2.7/site-packages/easygui ./Library/Python/2.7/site-packages/easygui/easygui.py ./Library/Python/2.7/site-packages/easygui/easygui.pyc ./Library/Python/2.7/site-packages/easygui-0.98.1.dist-info |
You can connect to Python 2.7 in a Terminal session. Then, you use the easygui
library to run a Hello World! message box with the following commands in the Python shell:
import easygui easy gui.msgbox("Hello World!") |
It will raise the following image:
Hopefully, this helps a few folks.
Python variable not defined
While working with a programming example for my students, I ran into an interesting run-time error when I changed their approach to importing Python’s random
module. Here’s the raised error message:
Traceback (most recent call last): File "windowBouncingBalls.py", line 84, in <module> speed = [choice([-2,2]), choice([-2,2])] NameError: name 'choice' is not defined |
You raise the missing choice
identifier when two things occur. The first thing requires you to use a standard import
statement, like the following example, and the second thing requires you to continue to reference the identifier as “choice
“.
import random |
You can avoid the error by making the import of random like this:
from random import * |
Or, you can leave the ordinary import statement and fully qualify the choice
identifier with the random
module name, like this:
speed = [random.choice([-2,2]), random.choice([-2,2])] |
As always, I hope this helps those who encounter a similar problem.
Install PyGame on Fedora
The PyGame library is a wonderful tool for building games with Python. It lets you accomplish a great deal by simply managing events. You need to understand how to use Python functions, modules, and events to build games with this Python library.
You can download and install the PyGame library with the yum utility like this:
yum install -y pygame |
It should generate the following list when you install it as the root
user:
Loaded plugins: langpacks, refresh-packagekit Available Packages pygame.x86_64 1.9.1-14.fc20 fedora [root@localhost ~]# yum install -y pygame Loaded plugins: langpacks, refresh-packagekit Resolving Dependencies --> Running transaction check ---> Package pygame.x86_64 0:1.9.1-14.fc20 will be installed --> Processing Dependency: numpy for package: pygame-1.9.1-14.fc20.x86_64 --> Processing Dependency: libportmidi.so.0()(64bit) for package: pygame-1.9.1-14.fc20.x86_64 --> Processing Dependency: libSDL_ttf-2.0.so.0()(64bit) for package: pygame-1.9.1-14.fc20.x86_64 --> Processing Dependency: libSDL_mixer-1.2.so.0()(64bit) for package: pygame-1.9.1-14.fc20.x86_64 --> Processing Dependency: libSDL_image-1.2.so.0()(64bit) for package: pygame-1.9.1-14.fc20.x86_64 --> Running transaction check ---> Package SDL_image.x86_64 0:1.2.12-7.fc20 will be installed ---> Package SDL_mixer.x86_64 0:1.2.12-5.fc20 will be installed --> Processing Dependency: libmikmod for package: SDL_mixer-1.2.12-5.fc20.x86_64 ---> Package SDL_ttf.x86_64 0:2.0.11-4.fc20 will be installed ---> Package numpy.x86_64 1:1.8.2-2.fc20 will be installed --> Processing Dependency: python-nose for package: 1:numpy-1.8.2-2.fc20.x86_64 ---> Package portmidi.x86_64 0:217-9.fc20 will be installed --> Running transaction check ---> Package libmikmod.x86_64 0:3.3.6-3.fc20 will be installed ---> Package python-nose.noarch 0:1.3.0-1.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: pygame x86_64 1.9.1-14.fc20 fedora 2.1 M Installing for dependencies: SDL_image x86_64 1.2.12-7.fc20 fedora 41 k SDL_mixer x86_64 1.2.12-5.fc20 fedora 91 k SDL_ttf x86_64 2.0.11-4.fc20 fedora 22 k libmikmod x86_64 3.3.6-3.fc20 updates 142 k numpy x86_64 1:1.8.2-2.fc20 updates 3.0 M portmidi x86_64 217-9.fc20 fedora 26 k python-nose noarch 1.3.0-1.fc20 fedora 272 k Transaction Summary ================================================================================ Install 1 Package (+7 Dependent packages) Total download size: 5.7 M Installed size: 21 M Downloading packages: (1/8): SDL_image-1.2.12-7.fc20.x86_64.rpm | 41 kB 00:00 (2/8): SDL_mixer-1.2.12-5.fc20.x86_64.rpm | 91 kB 00:00 (3/8): portmidi-217-9.fc20.x86_64.rpm | 26 kB 00:00 (4/8): SDL_ttf-2.0.11-4.fc20.x86_64.rpm | 22 kB 00:00 (5/8): libmikmod-3.3.6-3.fc20.x86_64.rpm | 142 kB 00:00 (6/8): numpy-1.8.2-2.fc20.x86_64.rpm | 3.0 MB 00:02 (7/8): pygame-1.9.1-14.fc20.x86_64.rpm | 2.1 MB 00:01 (8/8): python-nose-1.3.0-1.fc20.noarch.rpm | 272 kB 00:00 -------------------------------------------------------------------------------- Total 1.7 MB/s | 5.7 MB 00:03 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : SDL_ttf-2.0.11-4.fc20.x86_64 1/8 Installing : SDL_image-1.2.12-7.fc20.x86_64 2/8 Installing : portmidi-217-9.fc20.x86_64 3/8 Installing : libmikmod-3.3.6-3.fc20.x86_64 4/8 Installing : SDL_mixer-1.2.12-5.fc20.x86_64 5/8 Installing : python-nose-1.3.0-1.fc20.noarch 6/8 Installing : 1:numpy-1.8.2-2.fc20.x86_64 7/8 Installing : pygame-1.9.1-14.fc20.x86_64 8/8 Verifying : pygame-1.9.1-14.fc20.x86_64 1/8 Verifying : SDL_mixer-1.2.12-5.fc20.x86_64 2/8 Verifying : python-nose-1.3.0-1.fc20.noarch 3/8 Verifying : libmikmod-3.3.6-3.fc20.x86_64 4/8 Verifying : 1:numpy-1.8.2-2.fc20.x86_64 5/8 Verifying : portmidi-217-9.fc20.x86_64 6/8 Verifying : SDL_image-1.2.12-7.fc20.x86_64 7/8 Verifying : SDL_ttf-2.0.11-4.fc20.x86_64 8/8 Installed: pygame.x86_64 0:1.9.1-14.fc20 Dependency Installed: SDL_image.x86_64 0:1.2.12-7.fc20 SDL_mixer.x86_64 0:1.2.12-5.fc20 SDL_ttf.x86_64 0:2.0.11-4.fc20 libmikmod.x86_64 0:3.3.6-3.fc20 numpy.x86_64 1:1.8.2-2.fc20 portmidi.x86_64 0:217-9.fc20 python-nose.noarch 0:1.3.0-1.fc20 Complete! |
I hope this helps folks install the software.
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.