title: Permission denied after using PyInstaller to create Python executable
body: <p>I've created a little web server using the Bottle framework to serve up one webpage.  This is done by my python script "hello.py".  From the webpage generated by "hello.py", I'm able to edit the contents of a file called "data.txt".  This all works perfectly fine when I run "hello.py" from my terminal (python hello.py).  </p>
  
  <p><strong>But when I create an executable using PyInstaller I run into a problem.
  I'm unable to write to my "data.txt" file.  The error message I get is "Permission denied".  Everything else in the executable works except this!</strong></p>
  
  <p>Prior to creating my executable, I set the "data.txt" permissions to 777.    This didn't help.  I also tried a potential solution I found here - but no luck.  It looked like this:</p>
  
  <pre><code>def resource_path(relative_path):
          """ Get absolute path to resource, works for dev and for PyInstaller """
          try:
              # PyInstaller creates a temp folder and stores path in _MEIPASS
              base_path = sys._MEIPASS
          except Exception:
              base_path = os.path.abspath(".")
  
      return os.path.join(base_path, relative_path)
  
  def fix_ownership(path):
  """Change the owner of the file to SUDO_UID"""
  
  uid = os.environ.get('SUDO_UID')
  gid = os.environ.get('SUDO_GID')
  if uid is not None:
      os.chown(resource_path(path), int(uid), int(gid))
  
  @post('/data&lt;dataValue&gt;') # or @route('/login')
  def data(dataValue):
      thePostRequest = str(request.query_string)
      newPostRequest = string.replace(thePostRequest, '%22', '\"')
      fix_ownership("data.txt")
      with open("data.txt","w") as fo:
        fo.write('data = '+newPostRequest)
  
      return 
  </code></pre>
  
  <p>I had high hopes, but that didn't work either.  Here's my code as it stands now (I'm really new to Python so let me know of any glaring mistakes):</p>
  
  <pre><code>from bottle import route, run, static_file, get, post, request, response, redirect
  import os
  import string
  import sys
  
  def resource_path(relative_path):
      """ Get absolute path to resource, works for dev and for PyInstaller """
      try:
          # PyInstaller creates a temp folder and stores path in _MEIPASS
          base_path = sys._MEIPASS
      except Exception:
          base_path = os.path.abspath(".")
  
      return os.path.join(base_path, relative_path)
  
  
  @get('/Count&lt;deviceNumber&gt;') # or @route('/login')
  def Count(deviceNumber):
      return
  
  
  
  def fix_ownership(path):
      """Change the owner of the file to SUDO_UID"""
  
      uid = os.environ.get('SUDO_UID')
      gid = os.environ.get('SUDO_GID')
      if uid is not None:
          os.chown(resource_path(path), int(uid), int(gid))
  
  
  
  @post('/data&lt;dataValue&gt;') # or @route('/login')
  def data(dataValue):
      thePostRequest = str(request.query_string)
      newPostRequest = string.replace(thePostRequest, '%22', '\"')
      newPostRequest = newPostRequest.replace('%27', '\'')
  
  # THIS DOES NOT WORK AFTER EXECUTABLE IS CREATED BY PYINSTALLER - PERMISSION DENIED :(
      with open("data.txt","w") as fo:
        fo.write('data = '+newPostRequest)
  
      return
  
  
  
  @get('/ajax&lt;noCache&gt;') # or @route('/login')
  def ajax(noCache):
      return
  
  @get('/&lt;filename:re:.*\.(jpg|png|gif|ico)&gt;')
  def send_image(filename):
      print "getting image..."
      return static_file(filename, root=resource_path('./'))
  
  @get('/&lt;filename:path&gt;')
  def send_static(filename):
      return static_file(filename, root=resource_path('./'))
  
       #   return static_file(filename, root=os.path.join(sys._MEIPASS, './'))
  
  
  
  @route('/formSubmit', method='POST')
  def formSubmit():
      redirect("/hello", 303)
      return
  
  
  @route('/hello')
  @route('/hello', method='GET')
  def hello():
      return '''
  
      &lt;!DOCTYPE html&gt;
  
  &lt;html&gt;
      &lt;head&gt;
  &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
  &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
  &lt;!-- &lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&gt;
   --&gt;
  
  
        &lt;script type="text/javascript" src="data.txt"&gt;&lt;/script&gt;
        &lt;script type="text/javascript" src="myJavascript.js"&gt;&lt;/script&gt;
        &lt;link rel="stylesheet" type="text/css" href="style.css"&gt;&lt;/script&gt;
  
  
          &lt;title&gt;CANARI JR. | Home&lt;/title&gt;
  
  
  
   &lt;/head&gt;
  
  
  &lt;body onload="preparePage()"&gt;
  &lt;div id="spinner"&gt;&lt;/div&gt; 
  
  &lt;div id="container"&gt;
  
  
      &lt;div id="headerDiv"&gt;
  
          &lt;div id="logoDiv"&gt;&lt;a href="/" onclick="showHome(); return false;"&gt;
           &lt;img src="cLogo.png" alt="Canari Jr. Logo"&gt; 
           &lt;/a&gt;
          &lt;/div&gt;
  
  
          &lt;div id="navDiv"&gt;
          &lt;a href="/" onclick="showHome(); return false;"&gt;&lt;p id="homeBtn" style="color:black;background-color:white"&gt;Home&lt;/p&gt;&lt;/a&gt;
          &lt;a href="/" onclick="showSetup(); return false;"&gt;&lt;p id="settingsBtn"&gt;Settings&lt;/p&gt;&lt;/a&gt;
  
          &lt;/div&gt;
  
  
  
  
  
       &lt;/div&gt;
  
  
  
  &lt;div id="contentDiv"&gt;
  
  
  &lt;/div&gt;
  
  
  &lt;div id="addDiv" style="text-align:center;display:none;"&gt;
  &lt;h2&gt;Add New Device&lt;/h2&gt;
  &lt;form method="POST" id="deviceForm" action="/formSubmit" onsubmit="writeTxt('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P');"&gt;
  
  
  &lt;p style="background-color:#f5f5f5;" id="deviceDropdown"&gt;Monitor Type:&lt;select name="" id="deviceList" onchange="loadContentA(this.value)"&gt;
    &lt;option value="default"&gt;Choose one...&lt;/option&gt;
    &lt;option value="temp"&gt;Temperature&lt;/option&gt;
    &lt;option value="humidity"&gt;Humidity&lt;/option&gt;
    &lt;option value="analog"&gt;Analog&lt;/option&gt;
    &lt;option value="digital"&gt;Digital&lt;/option&gt;
    &lt;option value="counter"&gt;Counter&lt;/option&gt;
  &lt;/select&gt;&lt;/p&gt;
  
  
  &lt;div id="clearDiv" style="clear:both"&gt;&lt;/div&gt;
  &lt;a href="/" id="cancelBtn" onclick="hideAddDiv(); return false;"&gt;Cancel&lt;/a&gt;
  
  &lt;/form&gt;
  &lt;/div&gt;
  
  
  &lt;div id="editDiv" style="display:none"&gt;
  
  
  &lt;/div&gt;
  
  
  &lt;div id="setupDiv" style="display:none"&gt;
  &lt;h2 style="margin-bottom:35px; border:3px solid #8C8C8C; width:40%; margin:0 auto; padding:10px"&gt;Change IP Address&lt;/h2&gt;
  &lt;form method="POST" onsubmit="submitIP('ipAddress'); return false;"&gt;
  &lt;p&gt;New IP Address:  &lt;input type="text" name="ipAddress" id="ipAddress"&gt;&lt;input type="submit" value="Submit" style="padding:5px 10px 5px 10px"&gt;
  &lt;/p&gt;
  &lt;p&gt;Make sure to &lt;span style="color:red"&gt;write down this IP Address&lt;/span&gt; as you will need it to complete setup.&lt;/p&gt;&lt;br&gt;
  &lt;/form&gt;
  
  &lt;h2 style="margin-bottom:35px; border:3px solid #8C8C8C; width:40%; margin:0 auto; padding:10px;margin-top:45px;"&gt;Binding Mode&lt;/h2&gt;
  &lt;p&gt;Binding Mode is currently:&lt;/p&gt;
  &lt;a href="/" id="bindBtn" onclick="bindOn(); return false;" class="btn"&gt;OFF&lt;/a&gt;
  &lt;p&gt;(Click to change)&lt;/p&gt;
  
  
  &lt;/div&gt;
  
  
  
  &lt;/div&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  
  
      '''
  run(host='0.0.0.0', port=8080, debug=True)
  </code></pre>
  
  <p>I'm using Mac OSX.</p>