# Python in CG Production

{% embed url="<https://vfxplatform.com/>" %}
Driven by Autodesk
{% endembed %}

* Windows: make sure to install 64bit version of [Python 3](https://wsvincent.com/install-python3-windows/)
* MacOS: use [Homebrew](https://brew.sh/) to install [Python 3](https://docs.python-guide.org/starting/install3/osx/)

### IDE

An Integrated Development Environment (IDE) is an essential tool for software development. Offering numerous time-saving and productivity features, an IDE should provide the foundation for every TD's development environment.

**IDEs for Python Development**

* [Visual Studio Code](https://code.visualstudio.com/)
* [Sublime Text](https://www.sublimetext.com/)
* [PyCharm](https://www.jetbrains.com/pycharm/)
* [Atom](https://atom.io/)&#x20;
* [Eclipse](https://www.eclipse.org/ide/) + [PyDev](http://www.pydev.org/)&#x20;

**Visual Studio Code References**

* [Python in Visual Studio Code](https://code.visualstudio.com/docs/languages/python)
* [Getting Started with Python in VS Code](https://code.visualstudio.com/docs/python/python-tutorial)&#x20;

### What are Packages?

* A single Python file is a module
* A package is a folder containing Python files (modules) and an **\_\_init\_\_.py** file
* The **\_\_init\_\_.py** file distinguishes it as a package. Otherwise, it is just a directory containing Python files.

### Popular 3rd Party Packages

* PySide2 - UI
* NumPy - Scientific Computing
* Pylint - Code Analysis
* Django - Web Framework
* Pillow - Image Manipulation

Installing Packages from PyPI use **pip.**

### Virtual Environments

To find out where all the installed packages are located we can use the following command in an interactive session:

```python
import site
site.getsitepackages()
```

#### Creating Virtual Environments

The **venv** module provides support for creating and activating a virtual environment. This is available since Python 3.3 and it is the recommended method as of Python 3.5.

```bash
python -m venv <environment name> (i.e. numpy_latest)
(macOS) source ./venv/bin/activate 
(Windows) ./venv/bin/Activate.ps1 (or ./venv/Scripts/Activate.ps1)
```

### Standalone Qt Application (example)

```python
import sys
from PySide2 import QtWidgets

class StandaloneWindow(QtWidgets.QWidget):

    def __init__(self):
        super(StandaloneWindow, self).__init__(parent=None)

        self.setWindowTitle("Standalone App")
        self.setMinimumSize(400, 300)

        self.close_btn = QtWidgets.QPushButton("Close", self)
        self.close_btn.clicked.connect(self.close)


if __name__ == "__main__":
    # Create the main Qt application
    app = QtWidgets.QApplication(sys.argv)

    window = StandaloneWindow()
    window.show()

    # Enter Qt main loop (start event handling)
    app.exec_()

```

By default the color palette for QT seems outdated, but can be changed fairly easily to a modern dark theme using the [QPalette Class](https://doc.qt.io/qt-5/qpalette.html). Here we are mostly interested in the [ColorRole](https://doc.qt.io/qt-5/qpalette.html#ColorRole-enum). But first we need to define the style we want to use, in my case I picked "fusion".

```python
app.setStyle(QtWidgets.QStyleFactory.create("fusion"))

dark_palette = QtGui.QPalette()
dark_palette.setColor(QtGui.QPalette.Window, QtGui.QColor(45, 45, 45))
dark_palette.setColor(QtGui.QPalette.WindowText, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.Base, QtGui.QColor(25, 25, 25))
dark_palette.setColor(QtGui.QPalette.AlternateBase, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.ToolTipBase, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.ToolTipBase, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.Text, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.Button, QtGui.QColor(45, 45, 48))
dark_palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor(208, 208, 208))
dark_palette.setColor(QtGui.QPalette.BrightText, QtCore.Qt.red)
dark_palette.setColor(QtGui.QPalette.Link, QtGui.QColor(42, 130, 218))
dark_palette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(42, 130, 218))
dark_palette.setColor(QtGui.QPalette.Highlight, QtCore.Qt.black)
app.setPalette(dark_palette)
```

Technically, we could go into the nitty-gritty and modify everything. All we have to do is look at the documentation for the [QStyle class](https://doc.qt.io/qt-5/qstyle.html).&#x20;

### JSON (JavaScript Object Notation)

* Standardized format for storing and exchanging data, including
  * Storing configurations
  * Managing metadata (e.g. assets or shots)
  * Communicating between different applications
* Human readable and easy to understand

#### JSON and Python

* Python has a build-in package called **json** for encoding and decoding JSON
* Serialization - The process of encoding JSON
  * *json.dump(data, file\_name)* or *json.dumps(data)*
* Deserialization - The process of decoding JSON
  * *json.load(file\_name)* or *json.loads(json\_string)*

### Automation with Sockets

* Sockets are the endpoints of a two-way communication link between two programs running on the network
* A client is the socket end that requests a connection
* A server is the socket end that listens for and allows remote connections
* Both the client and server can send and receive data

Maya doesn't allow direct connections, but we can use the IP address (local host) and a given port which can be a number between 1024 and 65535.

```python
import maya.cmds as cmds

cmds.commandPort(name="20180", sourceType="mel")
cmds.commandPort(name="20181", sourceType="python")
```

This can be added to the **userSetup.py** file in `Library/Preferences/Autodesk/maya/2018/scripts/userSetup.py` like so:&#x20;

```python
import maya.cmds as cmds

if not cmds.about(batch=True):
    cmds.commandPort(name="20180", sourceType="mel")
    cmds.commandPort(name="20181", sourceType="python")
```

The number given as name are based on the maya version e.g. 2018 and ending with a 0 for mel and a 1 for python.

BUFFER\_SIZE = 4096 (usually, but can be changed)
