Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I copy to the clipboard the output of a cell in a Jupyter notebook?

How can I copy to the clipboard the output of a cell in a Jupyter notebook, without having to select it with drag-and-drop?

enter image description here

like image 392
Franck Dernoncourt Avatar asked May 28 '17 16:05

Franck Dernoncourt


People also ask

What does %% capture do Jupyter?

Capturing Output With %%capture IPython has a cell magic, %%capture , which captures the stdout/stderr of a cell. With this magic you can discard these streams or store them in a variable. By default, %%capture discards these streams. This is a simple way to suppress unwanted output.

How do you paste a cell in a Jupyter notebook?

Copying and pasting cells BETWEEN notebooks: Notebook 1: — Select multiple cells by holding down Shift and hit Ctrl+c to copy. Notebook 2: — Hit Esc to enter Command mode Ctrl + v to paste.

How do I copy text from terminal Jupyter?

Copy/Paste For macOS users, Cmd+C and Cmd+V work as usual. For Windows users using PowerShell , Ctrl+Insert and Shift+Insert work as usual.


2 Answers

Jupyter notebook runs in browser so you can use some javascript to select and copy cells to clipboard. After some trial and error I came up with this bookmarklet:

javascript:(function%20()%20%7B%20function%20SelectText(element)%20%7B%20var%20range%3B%20var%20selection%3B%20if%20(document.body.createTextRange)%20%7B%20range%20%3D%20document.body.createTextRange()%3B%20range.moveToElementText(element)%3B%20range.select()%3B%20copy2clipboard(range.text%2C%20element.innerHTML)%3B%20document.getSelection().removeAllRanges()%3B%20%7D%20else%20if%20(window.getSelection)%20%7B%20selection%20%3D%20window.getSelection()%3B%20range%20%3D%20document.createRange()%3B%20range.selectNodeContents(element)%3B%20selection.removeAllRanges()%3B%20selection.addRange(range)%3B%20copy2clipboard(selection.toString()%2C%20element.innerHTML)%3B%20selection.removeAllRanges()%3B%20%7D%20%7D%3B%20function%20copy2clipboard(text%2C%20html)%20%7B%20function%20listener(e)%20%7B%20e.clipboardData.setData('text%2Fplain'%2C%20text)%3B%20e.clipboardData.setData('text%2Fhtml'%2C%20html)%3B%20e.preventDefault()%3B%20%7D%20document.addEventListener('copy'%2C%20listener)%3B%20document.execCommand('copy')%3B%20document.removeEventListener('copy'%2C%20listener)%3B%20%7D%3B%20%24('%23notebook-container').on('mouseenter'%2C%20'.input%2C%20.output_wrapper'%2C%20function%20()%20%7B%20if%20(%24(this).find('i%3Alast').length)%20%7B%20%24(this).find('i%3Alast').show()%3B%20%7D%20else%20%7B%20%24(this).css(%7B%20'position'%3A%20'relative'%20%7D).append(%24('%3Ci%20style%3D%22position%3Aabsolute%3B%20top%3A7px%3B%20left%3A%207px%3B%22%20class%3D%22fa-copy%20fa%22%3E%3C%2Fi%3E').on('click'%2C%20function%20()%20%7B%20SelectText(%24(this).parent().find('.input_area%2C%20.output')%20%5B0%5D)%3B%20%24(this).slideUp()%3B%20%7D))%3B%20%7D%20%7D)%3B%20%24('%23notebook-container').on('mouseleave'%2C%20'.input%2C%20.output_wrapper'%2C%20function%20()%20%7B%20%24(this).find('i%3Alast').hide()%3B%20%7D)%3B%20%7D)%20()%3B 

Add it to your bookmarks and run it on a notebook page.

How it works

  1. For every input and output cell it adds a small copy icon that shows on hover.
  2. Clicking on copy icon selects a corresponding cell content, sends it to clipboard and then deselects it. Content is copied in text/plain and text/html format so it can be used to copy text, tables, images and plots with formatting.
  3. After coping, icon disappears to give some feedback and shows on next hover event.

It should work on any modern browser including IE11.

Here is decoded source:

(function () {   function SelectText(element) {     var range;     var selection;     if (document.body.createTextRange) {       range = document.body.createTextRange();       range.moveToElementText(element);       range.select();       copy2clipboard(range.text, element.innerHTML);       document.getSelection().removeAllRanges();     } else if (window.getSelection) {       selection = window.getSelection();       range = document.createRange();       range.selectNodeContents(element);       selection.removeAllRanges();       selection.addRange(range);       copy2clipboard(selection.toString(), element.innerHTML);       selection.removeAllRanges();     }   };   function copy2clipboard(text, html) {     function listener(e) {       e.clipboardData.setData('text/plain', text);       e.clipboardData.setData('text/html', html);       e.preventDefault();     }     document.addEventListener('copy', listener);     document.execCommand('copy');     document.removeEventListener('copy', listener);   };   $('#notebook-container').on('mouseenter', '.input, .output_wrapper', function () {     if ($(this).find('i:last').length) {       $(this).find('i:last').show();     } else {       $(this).css({         'position': 'relative'       }).append($('<i style=\"position:absolute; top:7px; left: 7px;\" class=\"fa-copy fa\"></i>').on('click', function () {         SelectText($(this).parent().find('.input_area, .output') [0]);         $(this).slideUp();       }));     }   });   $('#notebook-container').on('mouseleave', '.input, .output_wrapper', function () {     $(this).find('i:last').hide();   }); }) (); 

Bookmarklet is created by removing newlines from code and running it through encodeURIComponent() function.

Old answer

There are several ways to copy data to clipboard in python using tkinter, win32 or ctypes. But if you are using Jupyter notebook, you probably also using pandas.

import pandas as pd df = pd.DataFrame(['Copy me to clipboard']) df.to_clipboard(index=False,header=False) 
like image 183
mx0 Avatar answered Sep 18 '22 16:09

mx0


You can try using pyperclip - a third-party package that copies strings to the system clipboard.

Given

import pyperclip as clip   # Sample Data res = [(str(x*100), x) for x in range(1, 10)] res 

Output

[('100', 1), ('200', 2), ('300', 3),  ('400', 4), ('500', 5), ('600', 6),   ('700', 7), ('800', 8), ('900', 9)] 

Code

clip.copy(f"{res}") #clip.copy("{}".format(res))                           # python < 3.6 clip.paste()                                           # or Ctrl + V 

Output

[('100', 1), ('200', 2), ('300', 3),  ('400', 4), ('500', 5), ('600', 6),  ('700', 7), ('800', 8), ('900', 9)] 
like image 25
pylang Avatar answered Sep 17 '22 16:09

pylang