Repository: pyinstaller/pyinstaller

Issue:
XDG_DATA_DIRS environment variable being overriden when running packaged app
I have a simple app that runs a local Flask web server and opens a web browser to show it on start up using the following command: 

    webbrowser.open('http://localhost:%d' % port, new=2, autoraise=True)

When I run it in development mode, this works fine. However, when it's packaged using pyinstaller and run as an executable, I get this:

    gvfs-open: http://localhost:5000: error opening location: No application is registered as handling this file

The order of the browser's web browser will try is the same in both instances: 

    'xdg-open', 'gvfs-open', 'gnome-open', 'x-www-browser', 'firefox'

I tried using specific commands using `webbrowser.get(NAME).open` but none worked (except Firefox). 

It seems like the XDG_DATA_DIRS environment variable is being over ridden: 

`print('XDG_DATA_DIRS: ' + os.environ.get('XDG_DATA_DIRS', 'not found'))` 

yields 

`/usr/share/ubuntu:/usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop:/var/lib/snapd/desktop` 

in development mode and 

`SOURCE_DIR/dist/linux/app/share`

in the packaged executable. 

I'm using Python 3.5.2 and pyinstaller 3.3.1 on Ubuntu 16.04 with the command 

    pyinstaller --add-data="static:static" app.py

Stack overflow link: https://stackoverflow.com/questions/51657864/pyinstaller-webbrowser-open-doesnt-work-in-packaged-app


Discussion:
I'm having the same issue. I worked around it by using some code from the pull request mentioned in the below issue and by using:
`subprocess.Popen(["xdg-open", "http://url.com", env=env)`
#2892
@teug91 by code from the merge request, do you mean this? 
https://github.com/ThomasWaldmann/borg/blob/b5069770b7d4eb454cd429a0e4e7b2347994add0/src/borg/helpers/process.py#L139

For me, the evn variable "XDG_DATA_DIRS_ORIG" is not found inside the packaged app. 
Yes. For my app, restoring "LD_LIBRARY_PATH" does the trick.

```
myEnv = dict(os.environ)
lp_key = 'LD_LIBRARY_PATH'
lp_orig = myEnv.get(lp_key + '_ORIG')
if lp_orig is not None:
    myEnv[lp_key] = lp_orig
else:
    lp = myEnv.get(lp_key)
    if lp is not None:
        myEnv.pop(lp_key)

subprocess.Popen(["xdg-open", "http://github.com", env=myEnv)
```
Yeah, that seems to do the trick. I'm not sure why unsetting LD_LIBRARY_PATH causes xdg-open to work but I guess I'll close this issue. 

Thanks! 
I still ran into this issue. The only way I'm able to start external applications reliably is by removing all environment variables that contain the 'tmp' directory. To open a file in its native application I used the following, which seems like a major hack to me but it's better than nothing...

```Python    
    myEnv = dict(os.environ)
      
    toDelete = [] 
    for (k, v) in myEnv.items():
        if k != 'PATH' and 'tmp' in v:
            toDelete.append(k)
        
    for k in toDelete:
        myEnv.pop(k, None)
    
    shell = False
    if sys.platform == "win32":
        opener = "start"
        shell = True
    elif sys.platform == "darwin":
        opener = "open"
    else: # Assume Linux
        opener = "xdg-open"
      
    subprocess.call([opener, path], env=myEnv, shell=shell)
    
 ```
I think this issue should still be marked as open. It appears to me to be a bug in PyInstaller that should be fixed, as opposed to being something that people can just use that workaround for. There are other use cases where that workaround can't be used. For example, using Qt's QDesktopServices.openUrl() (https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtGui/QDesktopServices.html), which calls the OS's default program to open a file and doesn't allow one to change the environment variables.
We ran into the same issue with `Gio.AppInfo.launch_default_for_uri` not being able to find any default application when called in a pyinstaller-frozen executable. Prepending to `XDG_DATA_DIRS` as done in this run-time hook https://github.com/livMatS/dtool-lookup-gui/blob/9c0fa56e4842c2913caa776a093ec1fad673dc3e/pyinstaller/rthooks/pyi_rth_glib.py instead of replacing it as currently done within https://github.com/pyinstaller/pyinstaller/blob/7d77825f42a5929d08b3337fd7b4550bc5387f42/PyInstaller/hooks/rthooks/pyi_rth_glib.py helps.

Resolving patch:
diff --git a/PyInstaller/hooks/rthooks/pyi_rth_glib.py b/PyInstaller/hooks/rthooks/pyi_rth_glib.py
--- a/PyInstaller/hooks/rthooks/pyi_rth_glib.py
+++ b/PyInstaller/hooks/rthooks/pyi_rth_glib.py
@@ -12,4 +12,20 @@
 import os
 import sys
 
-os.environ['XDG_DATA_DIRS'] = os.path.join(sys._MEIPASS, 'share')
+# Prepend the frozen application's data dir to XDG_DATA_DIRS. We need to avoid overwriting the existing paths in order
+# to allow the frozen application to run system-installed applications (for example, launch a web browser via the
+# webbrowser module on Linux). Should the user desire complete isolation of the frozen application from the system,
+# they need to clean up XDG_DATA_DIRS at the start of their program (i.e., remove all entries but first).
+pyi_data_dir = os.path.join(sys._MEIPASS, 'share')
+
+xdg_data_dirs = os.environ.get('XDG_DATA_DIRS', None)
+if xdg_data_dirs:
+    if pyi_data_dir not in xdg_data_dirs:
+        xdg_data_dirs = pyi_data_dir + os.pathsep + xdg_data_dirs
+else:
+    xdg_data_dirs = pyi_data_dir
+os.environ['XDG_DATA_DIRS'] = xdg_data_dirs
+
+# Cleanup aux variables
+del xdg_data_dirs
+del pyi_data_dir


Test patch: