9

How can I put a comment at the end of an IPython magic command?

Eg, trying to use %cd:

%cd "dir"  # comment

I want to change to directory dir but instead I get:

[Errno 2] No such file or directory: 'dir # comment'
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Tom Hale
  • 40,825
  • 36
  • 187
  • 242
  • Some magics appear to work with a comment, but this `cd` does not. I don't see an indication in the docs or other wise as to why there's a difference. If a `magic` takes flagged options, those strings are parsed either directly or by an `argparse` like parser. `%cd??` may be give further clues as to why it ignores the `#` comment character. – hpaulj Dec 13 '18 at 03:04
  • @hpaulj `%cd??` doesn't help. Have updated question with doco link. – Tom Hale Dec 13 '18 at 08:28

2 Answers2

1

It's not possible in general because IPython magic commands parse their own command lines.*

There are some magic commands where comments seem to work, but actually they're being handled in another way. For example:

  • %ls # comment works properly, but %ls is an alias to a shell command, so the shell is what's parsing the comment.
  • %automagic 0 # comment behaves like %automagic, toggling the setting instead of exclusively disabling it like %automagic 0 would do. It's as if the 0 # comment is all one string, which it ignores.
  • %run $filename # comment treats the comment as arguments, so ['#', 'comment'] ends up in sys.argv for $filename.

Workaround

You could call magic commands using exclusively Python syntax.

First get the running IPython instance with get_ipython():

ipython = get_ipython()

Then:

ipython.run_line_magic('cd', 'dir')  # comment

Or for cell magics, you could go from this (which doesn't work):

%%script bash  # comment
echo hello

to this:

ipython.run_cell_magic('script', 'bash', 'echo hello')  # comment

Another option, I suppose, is to run an entire cell, although, suppressing the output since it returns an ExecutionResult object:

ipython.run_cell('%cd dir');  # comment

* I'm not sure if this is documented explicitly, but it is documented implicitly under defining custom magics, and I found the clues in this GitHub issue: Allow comments after arguments in magic_arguments.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
-1

TL;DR: You cannot as things stand. This might or might not be an error in the implementation of %cd.

Until this is fixed, one way to avoid this is to use:

import os
os.chdir("dir") #some comment here

A second alternative is using bash commands. However % is a magic command, not equivalent to a bash command. This is on purpose, as it can change the current directory of the notebook.

This is not the same as e.g.

!cd dir #some comment here

Which will spawn a shell and execute the command there thus not changing the current directory. (You can verify using pwd before/after each command)

Note that if your goal is not to change the current jupyter notebook directory, you can issue multiple commands in one cell with the magic %sh:

%%sh 
cd dir #some comment here
ls #some more commands here
....

This command will spawn a shell and all bash commands will be executed there, so the current jupyter directory will not change.

ntg
  • 12,950
  • 7
  • 74
  • 95
  • `os.chdir()` is not really a replacement for `%cd`. For example, `%cd` on its own works and goes to your home directory, while `os.chdir()` on its own throws an error, `missing required argument 'path'`. `%cd` also supports tilde as a shorthand for your home directory, like for example, `%cd ~/projects`. – wjandrea Nov 28 '22 at 18:18
  • Sorry, why are you talking about shell commands? That's not what OP's asking about. – wjandrea Nov 28 '22 at 18:21
  • True, the OP is asking How to put a comment after a IPython magic command. The TL;DR answer is you can't until/unless %cd is fixed. – ntg Nov 30 '22 at 09:17
  • `%cd` can be replaced by the much less elegant (but still working if the notebook is ever converted/used to just python ) `os.chdir(os.path.expanduser('~'))` ; so does `%cd ~/projects` correspond to `os.chdir(os.path.expanduser('~/projects'))` It's up to you and your aesthetics if you'll go for this option or just skip / place the comments somewhere else, both are imperfect, please don't shoot the messenger:) – ntg Nov 30 '22 at 09:26
  • But the problem also isn't specific to `%cd`... For example, `%%script` is also affected, and there's no drop-in replacement for that as far as I know. *Although*, I posted a comment with maybe a better workaround: `ipython = get_ipython()` then `ipython.run_line_magic('cd', 'dir') # comment`. Or for cell magics, `ipython.run_cell_magic('script', 'bash', 'echo hello') # comment`. By all means put this in your answer if you want. – wjandrea Nov 30 '22 at 18:00
  • Those were just two examples and I know it's possible to replicate them in plain Python, but `%cd` has more capabilities, like `%cd -` to go to the previous WD and `%cd $foobar` to use a Python variable `foobar`. So it'd be better to use the `run_*_magic()` functions like I mentioned. – wjandrea Nov 30 '22 at 18:03
  • 1
    BTW, careful, [sh is not the same thing as Bash](/q/5725296/4518341). – wjandrea Nov 30 '22 at 18:17
  • Also, maybe this is nitpicking, but what makes you say it's an error in the implementation? I don't think the IPython documentation says how comments work with magic commands, so this seems like undefined behaviour if anything. And I found a [GitHub issue](https://github.com/ipython/ipython/issues/13012) where the discussion implies this is the behaviour the implementers intended, even if it's not documented. – wjandrea Nov 30 '22 at 18:26
  • It could be by design. The reason I am supposing this is that other commands seem to be taking comments ok... e.g. one can do `%ls .. . #comment`. Also I think I did a small search at the time I answered this and there were other people believing this - I dont remember finding something concrete though. What is your opinion on the matter? – ntg Nov 30 '22 at 19:05
  • Hmm... `%ls` isn't *really* a magic command, it's an alias for a shell command. So the comment would be parsed by the shell, I suppose. BTW, there are other real magic commands that seem to allow comments, but actually they're just handling them other ways. For example, `%automagic 0 # comment` behaves like `%automagic`, as if the `0 # comment` is all one string, which it ignores. Ultimately, I guess the problem is that magics parse their own command lines. – wjandrea Nov 30 '22 at 19:20
  • 1
    I opted to post my own answer. Thanks for spurring that :) I learned some stuff about IPython along the way while trying to figure out how this actually works. – wjandrea Nov 30 '22 at 20:12