I thought it would be useful to provide an equivalent guide for Oracle Solaris, so here it is.
Oracle Solaris has a long history of involvement with Python, starting at least 15 years ago (if not more!). Our Image Packaging System is about 94-95% Python, and we've got about 440k LoC (lines of code) written in Python directly in the ON consolidation. When you look at the Userland consolidation, however, that list grows considerably. From a practical point of view, you cannot install Oracle Solaris without using Python, and nor can you have a supportable installation unless you have this system-delivered Python and a whole lot of packages in /usr/lib/python2.7/vendor-packages. We are well aware of the immininent end of support for Python 2.7 so work is underway on migrating not just our modules and commands, but also our tooling -- so that we're not stuck when 2020 arrives.
So how does one find which libraries and modules we ship, without trawling through P5M files in the Userland gate? Simply search through the Oracle Solaris IPS publisher either using the web interface (ala https://pkg.oracle.com) or using the command line:
$ pkg search -r \<python\>
which gives you a lot of package names. You'll notice that we version them via a suffix, so while you do get a few screenfuls of output, the list is about 423 packages long. Then to install it's very simple:
# pkg install <name-of-package>
just like you would for any other package.
# pkg install -v cx_oracle Packages to install: 7 Mediators to change: 1 Estimated space available: 22.67 GB Estimated space to be consumed: 1.01 GB Create boot environment: No Create backup boot environment: No Rebuild boot archive: No Changed mediators: mediator instantclient: version: None -> 12.2 (vendor default) Changed packages: solaris consolidation/instantclient/instantclient-incorporation None -> 188.8.131.52.0-4 database/oracle/instantclient-122 None -> 184.108.40.206.0-4 developer/oracle/odpi None -> 2.1.0-220.127.116.11.0.21.0 library/python/cx_oracle None -> 6.1-18.104.22.168.0.21.0 library/python/cx_oracle-27 None -> 6.1-22.214.171.124.0.21.0 library/python/cx_oracle-34 None -> 6.1-126.96.36.199.0.21.0 library/python/cx_oracle-35 None -> 6.1-188.8.131.52.0.21.0
Then it's a simple matter of firing up your preferred Python version and uttering import cx_Oracle and away you go. Much like this:
>>> import cx_Oracle >>> tns = """ORCLDNFS=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbkz)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcldnfs)))""" >>> user = "admin" >>> passwd = "welcome1" >>> cnx = cx_Oracle.connect(user, passwd, tns) >>> stmt = "select wait_class from v$system_event group by wait_class" >>> curs = cnx.cursor() >>> curs.execute(stmt).fetchall() [('Concurrency',), ('User I/O',), ('System I/O',), ('Scheduler',), ('Configuration',), ('Other',), ('Application',), ('Queueing',), ('Idle',), ('Commit',), ('Network',)]
While we do aim to package and deliver useful packages, it does happen that perhaps there's a package you need which we don't ship, or which we ship an older version of. How do you get past that problem in a fashion which doesn't affect your system installation?
Unsurprisingly, the answer is not specific to Oracle Solaris: use Python Virtual Environments. While you could certainly use
$ pip install --user
you can still run afoul of incorrect versions of modules being loaded. Using a virtual environment is cheap, fits in very well with the concept of containerization, and makes the task of producing reproducible builds (aka deterministic compilation much simpler.
For further information about Python packaging, please visit this tutorial, and review this article on Best Practices for Python dependency management which I've found to be one of the best written explanations about what to do, and why to do so.