diff --git a/runtime/BrowserWindow.cpp b/runtime/BrowserWindow.cpp
index 4b96abe5..6279cd4b 100644
--- a/runtime/BrowserWindow.cpp
+++ b/runtime/BrowserWindow.cpp
@@ -1215,17 +1215,17 @@ void BrowserWindow::preferences()
 
     ConfigWindow *dlg = new ConfigWindow();
     dlg->setWindowTitle(QWidget::tr("Configuration"));
-    dlg->setPythonPath(settings.value("PythonPath").toString());
+    dlg->setPythonExecutable(settings.value("PythonExecutable").toString());
     dlg->setApplicationPath(settings.value("ApplicationPath").toString());
     dlg->setModal(true);
     ok = dlg->exec();
 
-    QString pythonpath = dlg->getPythonPath();
+    QString pythonexecutable = dlg->getPythonExecutable();
     QString applicationpath = dlg->getApplicationPath();
 
     if (ok)
     {
-        settings.setValue("PythonPath", pythonpath);
+        settings.setValue("PythonExecutable", pythonexecutable);
         settings.setValue("ApplicationPath", applicationpath);
     }
 }
diff --git a/runtime/ConfigWindow.cpp b/runtime/ConfigWindow.cpp
index 3fb1a273..c31345bf 100644
--- a/runtime/ConfigWindow.cpp
+++ b/runtime/ConfigWindow.cpp
@@ -17,6 +17,14 @@ ConfigWindow::ConfigWindow(QWidget *parent) :
     ui(new Ui::ConfigWindow)
 {
     ui->setupUi(this);
+
+#ifdef PYTHON2
+    ui->pythonExecutableLineEdit->setPlaceholderText(
+                QString(QWidget::tr("The Python 2 executable to use (may be within a virtual environment)")));
+#else
+    ui->pythonExecutableLineEdit->setPlaceholderText(
+                QString(QWidget::tr("The Python 3 executable to use (may be within a virtual environment)")));
+#endif
 }
 
 ConfigWindow::~ConfigWindow()
@@ -34,9 +42,9 @@ void ConfigWindow::on_buttonBox_rejected()
     this->close();
 }
 
-QString ConfigWindow::getPythonPath()
+QString ConfigWindow::getPythonExecutable()
 {
-    return ui->pythonPathLineEdit->text();
+    return ui->pythonExecutableLineEdit->text();
 }
 
 QString ConfigWindow::getApplicationPath()
@@ -45,9 +53,9 @@ QString ConfigWindow::getApplicationPath()
 }
 
 
-void ConfigWindow::setPythonPath(QString path)
+void ConfigWindow::setPythonExecutable(QString path)
 {
-    ui->pythonPathLineEdit->setText(path);
+    ui->pythonExecutableLineEdit->setText(path);
 }
 
 void ConfigWindow::setApplicationPath(QString path)
diff --git a/runtime/ConfigWindow.h b/runtime/ConfigWindow.h
index 0027a742..c4487fcc 100644
--- a/runtime/ConfigWindow.h
+++ b/runtime/ConfigWindow.h
@@ -26,10 +26,10 @@ public:
     explicit ConfigWindow(QWidget *parent = 0);
     ~ConfigWindow();
 
-    QString getPythonPath();
+    QString getPythonExecutable();
     QString getApplicationPath();
 
-    void setPythonPath(QString path);
+    void setPythonExecutable(QString path);
     void setApplicationPath(QString path);
 
 private slots:
@@ -38,7 +38,7 @@ private slots:
 
 private:
     Ui::ConfigWindow *ui;
-    QString m_pythonpath, m_applicationpath;
+    QString m_pythonexecutable, m_applicationpath;
 };
 
 #endif // CONFIGWINDOW_H
diff --git a/runtime/ConfigWindow.ui b/runtime/ConfigWindow.ui
index 40d87be4..8b379052 100644
--- a/runtime/ConfigWindow.ui
+++ b/runtime/ConfigWindow.ui
@@ -29,14 +29,24 @@
       <enum>QFormLayout::ExpandingFieldsGrow</enum>
      </property>
      <item row="0" column="0">
-      <widget class="QLabel" name="pythonPathLabel">
+      <widget class="QLabel" name="pythonExecutableLabel">
+       <property name="sizeIncrement">
+        <size>
+         <width>0</width>
+         <height>1</height>
+        </size>
+       </property>
        <property name="text">
-        <string>Python Path</string>
+        <string>Python Executable</string>
        </property>
       </widget>
      </item>
      <item row="0" column="1">
-      <widget class="QLineEdit" name="pythonPathLineEdit"/>
+      <widget class="QLineEdit" name="pythonExecutableLineEdit">
+       <property name="placeholderText">
+        <string>The python executable to use (may be within a virtual environment)</string>
+       </property>
+      </widget>
      </item>
      <item row="1" column="0">
       <widget class="QLabel" name="applicationPathLabel">
@@ -46,7 +56,11 @@
       </widget>
      </item>
      <item row="1" column="1">
-      <widget class="QLineEdit" name="applicationPathLineEdit"/>
+      <widget class="QLineEdit" name="applicationPathLineEdit">
+       <property name="placeholderText">
+        <string>The directory containing pgAdmin4.py (do not include the file name)</string>
+       </property>
+      </widget>
      </item>
     </layout>
    </item>
diff --git a/runtime/Server.cpp b/runtime/Server.cpp
index e5be2056..078ec1ac 100644
--- a/runtime/Server.cpp
+++ b/runtime/Server.cpp
@@ -22,183 +22,84 @@
 // App headers
 #include "Server.h"
 
-static void add_to_path(QString &python_path, QString path, bool prepend=false)
-{
-    if (!python_path.contains(path))
-    {
-        if (!prepend)
-        {
-            if (!python_path.isEmpty() && !python_path.endsWith(";"))
-                python_path.append(";");
-
-            python_path.append(path);
-        }
-        else
-        {
-            if (!python_path.isEmpty() && !python_path.startsWith(";"))
-                python_path.prepend(";");
-
-            python_path.prepend(path);
-        }
-    }
-}
-
 Server::Server(quint16 port)
 {
     // Appserver port
     m_port = port;
-    m_wcAppName = NULL;
 
     // Initialise Python
-    Py_NoSiteFlag=1;
-    Py_DontWriteBytecodeFlag=1;
-
-    // Python3 requires conversion of char  * to wchar_t *, so...
-#ifdef PYTHON2
-    Py_SetProgramName(PGA_APP_NAME.toUtf8().data());
-#else
-    char *appName = PGA_APP_NAME.toUtf8().data();
-    const size_t cSize = strlen(appName)+1;
-    m_wcAppName = new wchar_t[cSize];
-    mbstowcs (m_wcAppName, appName, cSize);
-    Py_SetProgramName(m_wcAppName);
-#endif
-
-    // Setup the search path
-    QSettings settings;
-    QString python_path = settings.value("PythonPath").toString();
+    Py_DontWriteBytecodeFlag = 1;
 
     // Get the application directory
-    QString app_dir = qApp->applicationDirPath(),
-            path_env = qgetenv("PATH"),
-            pythonHome;
-    QStringList path_list;
-    int i;
-
-#ifdef Q_OS_MAC
-    // In the case we're running in a release appbundle, we need to ensure the
-    // bundled virtual env is included in the Python path. We include it at the
-    // end, so expert users can override the path, but we do not save it, because
-    // if users move the app bundle, we'll end up with dead entries
+    QString appDir = qApp->applicationDirPath();
 
     // Build (and canonicalise) the virtual environment path
-    QFileInfo venvBinPath(app_dir + "/../Resources/venv/bin");
-    QFileInfo venvLibPath(app_dir + "/../Resources/venv/lib/python");
-    QFileInfo venvDynLibPath(app_dir + "/../Resources/venv/lib/python/lib-dynload");
-    QFileInfo venvSitePackagesPath(app_dir + "/../Resources/venv/lib/python/site-packages");
-    QFileInfo venvPath(app_dir + "/../Resources/venv");
-
-    // Prepend the bin directory to the path
-    add_to_path(path_env, venvBinPath.canonicalFilePath(), true);
-    // Append the path, if it's not already there
-    add_to_path(python_path, venvLibPath.canonicalFilePath());
-    add_to_path(python_path, venvDynLibPath.canonicalFilePath());
-    add_to_path(python_path, venvSitePackagesPath.canonicalFilePath());
-    add_to_path(pythonHome, venvPath.canonicalFilePath());
+#ifdef Q_OS_MAC
+    QFileInfo venvBinPath(appDir + "/../Resources/venv/bin");
 #elif defined(Q_OS_WIN)
-
-    // In the case we're running in a release application, we need to ensure the
-    // bundled virtual env is included in the Python path. We include it at the
-    // end, so expert users can override the path, but we do not save it.
-
-    // Build (and canonicalise) the virtual environment path
-    QFileInfo venvBinPath(app_dir + "/../venv");
-    QFileInfo venvLibPath(app_dir + "/../venv/Lib");
-    QFileInfo venvDLLsPath(app_dir + "/../venv/DLLs");
-    QFileInfo venvSitePackagesPath(app_dir + "/../venv/Lib/site-packages");
-    QFileInfo venvPath(app_dir + "/../venv");
-
-    // Prepend the bin directory to the path
-    add_to_path(path_env, venvBinPath.canonicalFilePath(), true);
-    // Append paths, if they're not already there
-    add_to_path(python_path, venvLibPath.canonicalFilePath());
-    add_to_path(python_path, venvDLLsPath.canonicalFilePath());
-    add_to_path(python_path, venvSitePackagesPath.canonicalFilePath());
-    add_to_path(pythonHome, venvPath.canonicalFilePath());
+    QFileInfo venvBinPath(appDir + "/../venv");
 #else
-    // Build (and canonicalise) the virtual environment path
-    QFileInfo venvBinPath(app_dir + "/../venv/bin");
-    QFileInfo venvLibPath(app_dir + "/../venv/lib/python");
-    QFileInfo venvDynLibPath(app_dir + "/../venv/lib/python/lib-dynload");
-    QFileInfo venvSitePackagesPath(app_dir + "/../venv/lib/python/site-packages");
-    QFileInfo venvPath(app_dir + "/../venv");
-
-    // Prepend the bin directory to the path
-    add_to_path(path_env, venvBinPath.canonicalFilePath(), true);
-    // Append the path, if it's not already there
-    add_to_path(python_path, venvLibPath.canonicalFilePath());
-    add_to_path(python_path, venvDynLibPath.canonicalFilePath());
-    add_to_path(python_path, venvSitePackagesPath.canonicalFilePath());
-    add_to_path(pythonHome, venvPath.canonicalFilePath());
+    QFileInfo venvBinPath(appDir + "/../venv/bin");
 #endif
+    QString binPath = venvBinPath.canonicalFilePath();
 
-    qputenv("PATH", path_env.toUtf8().data());
-
-    if (python_path.length() > 0)
+    if (binPath.isEmpty())
     {
-        // Split the path setting into individual entries
-        path_list = python_path.split(";", QString::SkipEmptyParts);
-        python_path = QString();
-
-        // Add new additional path elements
-        for (i = path_list.size() - 1; i >= 0 ; --i)
-        {
-            python_path.append(path_list.at(i));
-            if (i > 0)
-            {
-#if defined(Q_OS_WIN)
-                python_path.append(";");
-#else
-                python_path.append(":");
-#endif
-            }
-        }
-        qputenv("PYTHONPATH", python_path.toUtf8().data());
+      // Use default Python environment from the config, or lastly, PATH
+      QSettings settings;
+      binPath.append(settings.value("PythonExecutable").toString());
+      if (binPath.isEmpty())
+          binPath.append("python");
     }
-
-    qDebug() << "Python path: " << python_path
-             << "\nPython Home: " << pythonHome;
-    if (!pythonHome.isEmpty())
+    else
     {
+      binPath.append("/python");
+    }
+
+    // Python3 requires conversion of char  * to wchar_t *, so...
 #ifdef PYTHON2
-        Py_SetPythonHome(pythonHome.toUtf8().data());
+    QByteArray appName = binPath.toLocal8Bit();
+    m_pyAppName = new char[strlen(appName.data()) + 1];
+    strcpy(m_pyAppName, appName.data());
+    qDebug() << "Python interpreter: " << QString::fromLocal8Bit(m_pyAppName);
 #else
-        char *python_home = pythonHome.toUtf8().data();
-        const size_t cSize = strlen(python_home) + 1;
-        wchar_t* wcPythonHome = new wchar_t[cSize];
-        mbstowcs (wcPythonHome, python_home, cSize);
-
-        Py_SetPythonHome(wcPythonHome);
+    std::wstring appName = binPath.toStdWString();
+    m_pyAppName = new wchar_t[wcslen(appName.c_str()) + 1];
+    wcscpy(m_pyAppName, appName.c_str());
+    qDebug() << "Python interpreter: " << QString::fromWCharArray(m_pyAppName);
 #endif
-    }
+    Py_SetProgramName(m_pyAppName);
 
     Py_Initialize();
 
+    /*
+     * Untrusted search path vulnerability in the PySys_SetArgv API function in Python 2.6 and earlier, and possibly later
+     * versions, prepends an empty string to sys.path when the argv[0] argument does not contain a path separator,
+     * which might allow local users to execute arbitrary code via a Trojan horse Python file in the current working directory.
+     * Here we have to set arguments explicitly to python interpreter. Check more details in 'PySys_SetArgv' documentation.
+     */
+    PySys_SetArgvEx(1, &m_pyAppName, 0);
+
     // Get the current path
     PyObject* sysPath = PySys_GetObject((char*)"path");
-
-    // Add new additional path elements
-    for (i = path_list.size() - 1; i >= 0 ; --i)
-    {
+    PyObject* sysPathRepr = PyObject_Repr(sysPath);
 #ifdef PYTHON2
-        PyList_Append(sysPath, PyString_FromString(path_list.at(i).toUtf8().data()));
+    qDebug() << "Python path: " << QString::fromLocal8Bit(PyString_AsString(sysPathRepr));
 #else
-#if PY_MINOR_VERSION > 2
-        PyList_Append(sysPath, PyUnicode_DecodeFSDefault(path_list.at(i).toUtf8().data()));
-#else
-        PyList_Append(sysPath, PyBytes_FromString(path_list.at(i).toUtf8().data()));
-#endif
+    PyObject* sysPathBytes = PyUnicode_AsEncodedString(sysPathRepr, "utf8", "replace");
+    qDebug() << "Python path: " << QString::fromUtf8(PyBytes_AsString(sysPathBytes));
+    Py_DECREF(sysPathBytes);
 #endif
-    }
+    Py_DECREF(sysPathRepr);
 }
 
 Server::~Server()
 {
-    if (m_wcAppName)
-        delete m_wcAppName;
-
     // Shutdown Python
     Py_Finalize();
+
+    if (m_pyAppName)
+        delete [] m_pyAppName;
 }
 
 bool Server::Init()
@@ -258,33 +159,11 @@ void Server::run()
 
     // Run the app!
 #ifdef PYTHON2
-    /*
-     * Untrusted search path vulnerability in the PySys_SetArgv API function in Python 2.6 and earlier, and possibly later
-     * versions, prepends an empty string to sys.path when the argv[0] argument does not contain a path separator,
-     * which might allow local users to execute arbitrary code via a Trojan horse Python file in the current working directory.
-     * Here we have to set arguments explicitly to python interpreter. Check more details in 'PySys_SetArgv' documentation.
-     */
-    char* n_argv[] = { m_appfile.toUtf8().data() };
-    PySys_SetArgv(1, n_argv);
-
     PyObject* PyFileObject = PyFile_FromString(m_appfile.toUtf8().data(), (char *)"r");
     int ret = PyRun_SimpleFile(PyFile_AsFile(PyFileObject), m_appfile.toUtf8().data());
     if (ret != 0)
         setError(tr("Failed to launch the application server, server thread exiting."));
 #else
-    /*
-     * Untrusted search path vulnerability in the PySys_SetArgv API function in Python 2.6 and earlier, and possibly later
-     * versions, prepends an empty string to sys.path when the argv[0] argument does not contain a path separator,
-     * which might allow local users to execute arbitrary code via a Trojan horse Python file in the current working directory.
-     * Here we have to set arguments explicitly to python interpreter. Check more details in 'PySys_SetArgv' documentation.
-     */
-    char *appName = m_appfile.toUtf8().data();
-    const size_t cSize = strlen(appName)+1;
-    wchar_t* wcAppName = new wchar_t[cSize];
-    mbstowcs (wcAppName, appName, cSize);
-    wchar_t* n_argv[] = { wcAppName };
-    PySys_SetArgv(1, n_argv);
-
     int fd = fileno(cp);
     PyObject* PyFileObject = PyFile_FromFd(fd, m_appfile.toUtf8().data(), (char *)"r", -1, NULL, NULL,NULL,1);
     if (PyRun_SimpleFile(fdopen(PyObject_AsFileDescriptor(PyFileObject),"r"), m_appfile.toUtf8().data()) != 0)
diff --git a/runtime/Server.h b/runtime/Server.h
index 8df8503b..5cc51f3d 100644
--- a/runtime/Server.h
+++ b/runtime/Server.h
@@ -39,7 +39,11 @@ private:
     QString m_error;
 
     quint16  m_port;
-    wchar_t *m_wcAppName;
+#ifdef PYTHON2
+    char *m_pyAppName;
+#else
+    wchar_t *m_pyAppName;
+#endif
 };
 
 #endif // SERVER_H
diff --git a/runtime/pgAdmin4.cpp b/runtime/pgAdmin4.cpp
index b1f470d8..e295e17b 100644
--- a/runtime/pgAdmin4.cpp
+++ b/runtime/pgAdmin4.cpp
@@ -72,68 +72,63 @@ int main(int argc, char * argv[])
 
     // Fire up the webserver
     Server *server;
+    server = new Server(port);
 
-    bool done = false;
+    if (!server->Init())
+    {
+        qDebug() << server->getError();
+
+        QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
+        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
+
+        exit(1);
+    }
 
-    while (done != true)
+    server->start();
+
+    // This is a hack. Wait a second and then check to see if the server thread
+    // is still running. If it's not, we probably had a startup error
+    delay(1000);
+
+    // Any errors?
+    if (server->isFinished() || server->getError().length() > 0)
     {
-        server = new Server(port);
+        splash->finish(NULL);
 
-        if (!server->Init())
-        {
-            qDebug() << server->getError();
+        qDebug() << server->getError();
 
-            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
-            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
+        QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
+        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
 
-            exit(1);
-        }
+        // Allow the user to tweak the Python Path if needed
+        QSettings settings;
+        bool ok;
 
-        server->start();
+        ConfigWindow *dlg = new ConfigWindow();
+        dlg->setWindowTitle(QWidget::tr("Configuration"));
+        dlg->setPythonExecutable(settings.value("PythonExecutable").toString());
+        dlg->setApplicationPath(settings.value("ApplicationPath").toString());
+        dlg->setModal(true);
+        ok = dlg->exec();
 
-        // This is a hack. Wait a second and then check to see if the server thread
-        // is still running. If it's not, we probably had a startup error
-        delay(1000);
+        QString pythonexecutable = dlg->getPythonExecutable();
+        QString applicationpath = dlg->getApplicationPath();
 
-        // Any errors?
-        if (server->isFinished() || server->getError().length() > 0)
+        if (ok)
         {
-            splash->finish(NULL);
-
-            qDebug() << server->getError();
+            settings.setValue("PythonExecutable", pythonexecutable);
+            settings.setValue("ApplicationPath", applicationpath);
+            settings.sync();
 
-            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
-            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
+            QString msg = QString(QWidget::tr("Please restart the application to allow the changes to take effect."));
+            QMessageBox::information(NULL, QString(QWidget::tr("Restart")), msg);
 
-            // Allow the user to tweak the Python Path if needed
-            QSettings settings;
-            bool ok;
-
-            ConfigWindow *dlg = new ConfigWindow();
-            dlg->setWindowTitle(QWidget::tr("Configuration"));
-            dlg->setPythonPath(settings.value("PythonPath").toString());
-            dlg->setApplicationPath(settings.value("ApplicationPath").toString());
-            dlg->setModal(true);
-            ok = dlg->exec();
-
-            QString pythonpath = dlg->getPythonPath();
-            QString applicationpath = dlg->getApplicationPath();
-
-            if (ok)
-            {
-                settings.setValue("PythonPath", pythonpath);
-                settings.setValue("ApplicationPath", applicationpath);
-                settings.sync();
-            }
-            else
-            {
-                exit(1);
-            }
-
-            delete server;
+            exit(0);
         }
         else
-            done = true;
+        {
+            exit(1);
+        }
     }
 
 
