Repository: spyder-ide/spyder

Issue:
Error when trying to create spyder.lock on an unwritable config directory
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

Spyder failed to launch with error log of multiple neseted expception. After following exact sequnce of commands. 

conda create -n xxx python=3.6 pip numpy

conda install -c conda-forge pyautogui

conda install -c conda-forge pyinstaller

conda install -c anaconda pyqt

conda install -c anaconda pip

pip install pyqt5

### Traceback
```python-traceback
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 162, in lock
    symlink(str(os.getpid()), self.name)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 97, in symlink
    rename(newlinkname, filename)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\\Users\\sdesai\\.spyder-py3\\spyder.lock.1554264487277.newlink' -> 'C:\\Users\\sdesai\\.spyder-py3\\spyder.lock'

Traceback (most recent call last):
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 189, in lock
    kill(int(pid), 0)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 81, in kill
    raise OSError(errno.ESRCH, None)
ProcessLookupError: [Errno 3] None

Traceback (most recent call last):
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\app\start.py", line 157, in main
    lock_created = lock.lock()
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 212, in lock
    rmlink(self.name)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\external\lockfile.py", line 119, in rmlink
    os.remove(os.path.join(filename, 'symlink'))
PermissionError: [WinError 5] Access is denied: 'C:\\Users\\sdesai\\.spyder-py3\\spyder.lock\\symlink'

Traceback (most recent call last):
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\plugins\__init__.py", line 515, in <lambda>
    toggled=lambda checked: self.toggle_view(checked),
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\plugins\ipythonconsole.py", line 771, in toggle_view
    self.create_new_client(give_focus=False)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\plugins\ipythonconsole.py", line 1111, in create_new_client
    self.register_client(client)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\plugins\ipythonconsole.py", line 1307, in register_client
    self.main.historylog.add_history(client.history_filename)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\plugins\history.py", line 240, in add_history
    encoding.write(text, filename)
  File "D:\Anaconda\envs\Mau\lib\site-packages\spyder\utils\encoding.py", line 233, in write
    with open(filename, mode) as textfile:
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\sdesai\\.spyder-py3\\history.py'
```

## Versions

* Spyder version: 3.3.3 
* Python version: 3.7.3
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 10

### Dependencies

```
pyflakes >=0.6.0  :  2.1.1 (OK)
pycodestyle >=2.3 :  2.5.0 (OK)
pygments >=2.0    :  2.3.1 (OK)
sphinx >=0.6.6    :  1.8.5 (OK)
rope >=0.9.4      :  0.12.0 (OK)
jedi >=0.9.0      :  0.13.3 (OK)
nbconvert >=4.0   :  5.4.1 (OK)
pandas >=0.13.1   :  None (NOK)
numpy >=1.7       :  None (NOK)
sympy >=0.7.3     :  None (NOK)
cython >=0.21     :  None (NOK)
qtconsole >=4.2.0 :  4.4.3 (OK)
IPython >=4.0     :  7.4.0 (OK)
matplotlib >=2.0.0:  None (NOK)
pylint >=0.25     :  2.3.1 (OK)
```



Discussion:
Your error is caused because Spyder is unable to write into this directory:

    C:\\Users\\sdesai\\.spyder-py3

The most probable cause is that (at some point) you started Spyder as Administrator inside your account, which changed the write permissions of that directory.

Now you have to manually remove that directory, so that Spyder can recreate it again.

Besides, with the commands you posted:

> conda create -n xxx python=3.6 pip numpy
conda install -c conda-forge pyautogui
conda install -c conda-forge pyinstaller
conda install -c anaconda pyqt
conda install -c anaconda pip
pip install pyqt5

you're mixing packages from conda-forge, anaconda and pip, which is a recipe for disaster (all those packages are binary incompatible with each other). If you want to use packages in conda-forge, please use this commands instead:

    conda create -n xxx -c conda-forge python=3.6
    conda install -c conda-forge pyautogui
    conda install -c conda-forge pyinstaller
    conda install -c conda-forge pyqt

Finally, if you're planning to use pyinstaller to freeze a PyQt application, you need to use an environment with all packages installed with pip, like this:

    conda create -n xxx python=3.6
    pip install pyautogui
    pip install pyinstaller
    pip install pyqt5
Thank for your generous support, I was little aware of that Disaster thing you mentioned, but I came to this command flow after many intermediate errors. I will recreate the environment using your method.  
Thanks Again :) 

Resolving patch:
diff --git a/spyder/plugins/history.py b/spyder/plugins/history.py
--- a/spyder/plugins/history.py
+++ b/spyder/plugins/history.py
@@ -231,13 +231,23 @@ def add_history(self, filename):
         editor.set_font( self.get_plugin_font(), color_scheme )
         editor.toggle_wrap_mode( self.get_option('wrap') )
 
-        text, _ = encoding.read(filename)
+        # Avoid a possible error when reading the history file
+        try:
+            text, _ = encoding.read(filename)
+        except (IOError, OSError):
+            text = "# Previous history could not be read from disk, sorry\n\n"
         text = normalize_eols(text)
         linebreaks = [m.start() for m in re.finditer('\n', text)]
         maxNline = self.get_option('max_entries')
         if len(linebreaks) > maxNline:
             text = text[linebreaks[-maxNline - 1] + 1:]
-            encoding.write(text, filename)
+            # Avoid an error when trying to write the trimmed text to
+            # disk.
+            # See issue 9093
+            try:
+                encoding.write(text, filename)
+            except (IOError, OSError):
+                pass
         editor.set_text(text)
         editor.set_cursor_position('eof')
         
diff --git a/spyder/utils/external/lockfile.py b/spyder/utils/external/lockfile.py
--- a/spyder/utils/external/lockfile.py
+++ b/spyder/utils/external/lockfile.py
@@ -96,11 +96,14 @@ def symlink(value, filename):    #analysis:ignore
         try:
             rename(newlinkname, filename)
         except:
+            # This is needed to avoid an error when we don't
+            # have permissions to write in ~/.spyder
+            # See issues 6319 and 9093
             try:
                 os.remove(newvalname)
                 os.rmdir(newlinkname)
             except (IOError, OSError):
-                pass
+                return
             raise
 
     def readlink(filename):   #analysis:ignore


Test patch: