Repository: spyder-ide/spyder

Issue:
Copy file reference in variable explorer generates PicklingError
## Description

### What steps will reproduce the problem?

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

on attempt to copy from "Variable viewer" cell corresponding to closed file reference ("TextIOWrapper object of _io module")

### Traceback
```python-traceback
  File "C:\Anaconda\lib\site-packages\spyder\plugins\variableexplorer\widgets\collectionseditor.py", line 1037, in copy
    obj = self.delegate.get_value(idx)
  File "C:\Anaconda\lib\site-packages\spyder\plugins\variableexplorer\widgets\collectionseditor.py", line 1386, in get_value
    return self.parent().get_value(name)
  File "C:\Anaconda\lib\site-packages\spyder\plugins\variableexplorer\widgets\collectionseditor.py", line 1439, in get_value
    value = self.shellwidget.get_value(name)
  File "C:\Anaconda\lib\site-packages\spyder\plugins\ipythonconsole\widgets\namespacebrowser.py", line 99, in get_value
    timeout=CALL_KERNEL_TIMEOUT).get_value(name)
  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 542, in __call__
    call_dict, call_data, self._comm_id)
  File "C:\Anaconda\lib\site-packages\spyder\plugins\ipythonconsole\comms\kernelcomm.py", line 114, in _get_call_return_value
    call_dict, call_data, comm_id)
  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 420, in _get_call_return_value
    return self._sync_error(reply['value'])
  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 480, in _sync_error
    error_wrapper.raise_error()
  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 90, in raise_error
    raise self.etype(self)
Exception in comms call get_value:

  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 343, in _handle_remote_call
    self._set_call_return_value(msg_dict, return_value)

  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 376, in _set_call_return_value
    comm_id=self.calling_comm_id)

  File "C:\Anaconda\lib\site-packages\spyder_kernels\comms\commbase.py", line 245, in _send_message
    data, protocol=self._comms[comm_id]['pickle_protocol'])]

  File "C:\Anaconda\lib\site-packages\cloudpickle\cloudpickle.py", line 1125, in dumps
    cp.dump(obj)

  File "C:\Anaconda\lib\site-packages\cloudpickle\cloudpickle.py", line 482, in dump
    return Pickler.dump(self, obj)

  File "C:\Anaconda\lib\pickle.py", line 409, in dump
    self.save(obj)

  File "C:\Anaconda\lib\pickle.py", line 476, in save
    f(self, obj) # Call unbound method with explicit self

  File "C:\Anaconda\lib\site-packages\cloudpickle\cloudpickle.py", line 1010, in save_file
    raise pickle.PicklingError("Cannot pickle closed files")

_pickle.PicklingError: Cannot pickle closed files

```

## Versions

* Spyder version: 4.0.1 
* Python version: 3.6.7
* Qt version: 5.12.5
* PyQt5 version: 5.12.3
* Operating System: Windows 10

### Dependencies

```
atomicwrites >=1.2.0         :  1.3.0 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
cloudpickle >=0.5.0          :  1.2.2 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
intervaltree                 :  None (OK)
IPython >=4.0                :  7.11.1 (OK)
jedi =0.14.1                 :  0.14.1 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
numpydoc >=0.6.0             :  0.9.2 (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
psutil >=0.3                 :  5.6.7 (OK)
pygments >=2.0               :  2.5.2 (OK)
pylint >=0.25                :  2.4.4 (OK)
pyls >=0.31.2;<0.32.0        :  0.31.7 (OK)
zmq >=17                     :  18.1.1 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
qtawesome >=0.5.7            :  0.6.1 (OK)
qtconsole >=4.6.0            :  4.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
rtree >=0.8.3                :  0.9.3 (OK)
sphinx >=0.6.6               :  2.3.1 (OK)
spyder_kernels >=1.8.1;<2.0.0:  1.8.1 (OK)
watchdog                     :  None (OK)
cython >=0.21                :  0.29.14 (OK)
matplotlib >=2.0.0           :  3.1.2 (OK)
numpy >=1.7                  :  1.18.1 (OK)
pandas >=0.13.1              :  0.25.3 (OK)
scipy >=0.17.0               :  1.3.1 (OK)
sympy >=0.7.3                :  1.5.1 (OK)
```



Discussion:
> on attempt to copy from "Variable viewer" cell corresponding to closed file reference ("TextIOWrapper object of _io module")

Please post a simple code example that generates this kind of object.
Not sure about code example (( Sorry, I am new to Python
This happened in Spyder 4.0.1 - within the "Variable viewer" right clicking on the reference name to already closed file, and trying to copy the value - caused this error.

What I mean by file reference name:
``` python
f_name = 'bla.bla'
f = open(f_name, 'w')
f.close()
```

So trying to copy value of "f" - fails
>So trying to copy value of "f" - fails

And what should be the value of `f`?
Apparently, no value (at least human-readable)
![изображение](https://user-images.githubusercontent.com/15016229/73994825-24680280-4957-11ea-9f97-aefedb52e0f9.png)
On the image: ZA and ZE are example of such kind

I was writing some note - and decided to copy/paste the "ZA" line - outcome is a bug on attempt to copy   
Yes, but what do you expect to be the result of copying it?

If I do `a = [1, 2, 3]` and copy that fro the variable explorer and paste that on the editor I get 

` [1, 2, 3]`, what do you expect to get from copying a closed file handle?! I mean it is not really a bug 🤷‍♂ from my POV.
I guess, you are right)) I was hoping just to copy text: "TextIOWrapper of ....."
But it just kicked in the Bug report form, which I submitted (top post).
Not sure if it will be useful for anyone.  Frankly, I was not expecting such prompt reaction from all of you.... I am sorry, if it is not important
>But it just kicked in the Bug report form, which I submitted (top post).

Well, I am not seeing the report dialog. I see warning/error message. So probably the fix is that this should not trigger an error?

Good point - or remove copy option from context menu (for this data type)
@dalthviz, please solve this one by adding `PicklingError` on line `102` of the file that appears below:

https://github.com/spyder-ide/spyder/blob/cb9e8c1ad135ee65f1c62268c0a2ce2aab7e2514/spyder/plugins/ipythonconsole/widgets/namespacebrowser.py#L95-L103

So, `UnpicklingError` can be generated when Spyder is unable to deserialize the value that comes from the kernel; and `PicklingError` when the kernel is unable to serialize the value Spyder is asking for.

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole/widgets/namespacebrowser.py b/spyder/plugins/ipythonconsole/widgets/namespacebrowser.py
--- a/spyder/plugins/ipythonconsole/widgets/namespacebrowser.py
+++ b/spyder/plugins/ipythonconsole/widgets/namespacebrowser.py
@@ -16,7 +16,7 @@
 except AttributeError:
     time.monotonic = time.time
 
-from pickle import UnpicklingError
+from pickle import PicklingError, UnpicklingError
 
 from qtpy.QtWidgets import QMessageBox
 
@@ -99,7 +99,7 @@ def get_value(self, name):
                 timeout=CALL_KERNEL_TIMEOUT).get_value(name)
         except TimeoutError:
             raise ValueError(msg % reason_big)
-        except UnpicklingError:
+        except (PicklingError, UnpicklingError):
             raise ValueError(msg % reason_not_picklable)
 
     def set_value(self, name, value):


Test patch: