Python mode in Emacs: No such file or directory, pdb - python

I have a python script that I want to debug with python-mode. I read in this thread that I can debug my python script with M-x pdb, however I get the following error:
Searching for program: no such file or directory, pdb
I can provide python -m pdb my_source_file.py in the prompt in the minibuffer, but it would be nice if Emacs could infer this command directly from the file on which I run M-x pdb
Update:
Running on:
Red Hat Enterprise Linux Server release 5.1 (Tikanga)
Emacs 23.3.1
Differences between paths
I get different paths when I run M-: exec-path and when I run M-: (getenv "PATH") (the one returned by M-: (getenv "PATH") is longer).
With this:
Where is pdb located? How can I add it to the Emacs path?
Is there a way to ask Emacs to also look into the paths held by the environment variable PATH?

Further to my comment earlier, and your subsequent update to the question:
First figure out a value for $PATH that works in your terminal. Use which pdb to find where the pdb executable is located.
Then, set the $PATH environment variable explicitly in Emacs, and sync it to exec-path as follows:
(setenv "PATH" "/usr/local/bin:/usr/bin:/bin:/some/other/dir")
(setq exec-path (split-string (getenv "PATH") path-separator))
It's possible you would need to also explicitly set PYTHONPATH or similar environment variables; you can do that using lines like the "setenv" line above, or just use the exec-path-from-shell elisp package.
Update
Okay, so it turns out Emacs' pdb command isn't provided by python-mode, and it expects to find an executable called "pdb". The easy way to fix this, then is to create a shell wrapper called "pdb", in a directory on your $PATH:
#!/bin/sh
exec python -m pdb "$#"
(I found a note here suggesting this technique.)
The equivalent under Windows would be a file called pdb.bat, containing:
python -u -m pdb %1
(The -u prevents Python from buffering its output.)

To run the Python Debugger, M-x pdb expects to find an executable named pdb. While the pdb executable may exist in some Python distributions, it doesn't exist in all of them.
A proposal to fix this is in GNU bug report #21521: pdb default suggested command.
Until the bug is fixed, you can set the variable gud-pdb-command-name to define the command used to launch pdb. In .emacs, add...
(setq gud-pdb-command-name "python -m pdb")

At a shell prompt type
which pdb
In Emacs, type M-x customize. Select Programming > Tools > Gud. Set the value of gud-pdb-command-name to the path returned by which pdb.
If your version of Emacs presents a different organization for the customize menu, you could also try
C-h v gud-pdb-command-name
Then click on the customize link, and set the path to pdb there.
Though the instructions above are different, I found this out by reading "Running pdb under emacs" .

You can create a custom command like this:
;; PDB command line
(defun user-python-debug-buffer ()
"Run python debugger on current buffer."
(interactive)
(setq command (format "python -u -m pdb %s " (file-name-nondirectory buffer-file-name)))
(let ((command-with-args (read-string "Debug command: " command nil nil nil)))
(pdb command-with-args)))

In Emacs 23.3.1 and presumably higher, yet another variation is to use the Emacs shell, Eshell (M-x eshell). Under Eshell, there's a pre-existing, Lisp-based definition of pdb. These Lisp functions work in Eshell just like ordinary shell commands.
So pdb "./manage.py runserver" will start a Django server, for instance.

Everyone is going wild saying you gotta make a pdb file and make it an executable and then type ./pdb your_code.py. It is easier than that.
Be where you want to run the debugger from. Probably in your python file, maybe use M-x cd to get somewhere.
Then type: M-x pdb
It will prompt you with:
Run pdb (like this):
You want to make that look like:
Run pdb (like this): python -m pdb your_code.py
Sometimes if I want to run my code as a module.
Run pdb (like this): python -m pdb -m some_package.my_code
Then type help and go read this https://docs.python.org/3/library/pdb.html

My answer builds on what #Chad Nouis mentioned.
a link
However, I've added this to python-mode, everytime python-mode loads, it will set gud-pdb-command-name to "python -m pdb"
;; Set the PDB command
(add-hook 'python-mode-hook
(lambda () (setq gud-pdb-command-name "python -m pdb")))

Related

R: system() cannot use bash function defined in .bashrc

Question
My default Python is 2.7, but I have a script that requires Python 3.4. I am trying to create a function in R that will:
Switch to Python 3.4
Run this script
Switch back to Python 2.7
Import results into R
To switch between Python versions, I use my cluster's "dotkit" system, like this:
use Python-2.7
use Python-3.4
"use" is a bash function that is imported in my .bashrc file. It sets all of my path variables (PATH, LIBRARY_PATH, LD_LIBRARY_PATH, CPATH, C_INCLUDE_PATH, etc). The problem is that when I try to call this function in R, I get the following error:
system('use Python-3.4')
sh: use: command not found
It seems like this is a problem with my PATH. I am using the correct shell:
system('echo $SHELL')
/bin/bash
My $PATH variable also looks good. However, when I create a script that essentially does the same thing:
load_py34.sh:
#!/bin/bash
source ~/.bashrc
use Python-3.4
and call this script through R, then it actually runs, but for some reason, it doesn't change my python version within R. (I have verified that this script works from the command line.)
> R
> system('python --version')
Python 2.7.1
> system('sh load_py34.sh')
Prepending: R-3.4 (ok)
> system('python --version')
Python 2.7.1
So I'm a little confused, but if anyone can help, I would really appreciate it.
Suggested fixes
When I combine them into a single command, I still have the same problem:
> system("sh load_py34.sh; python --version")
Prepending: Python-3.4 (already loaded)
Python 2.7.1
When I try calling bash directly, I still have a problem with the PATH:
> system("bash -c 'use Python-3.4; python --version'")
bash: use: command not found
Python 2.7.1
.bashrc is only loaded for interactive bash sessions.
"use" is a bash function that is imported in my .bashrc file. It sets
all of my path variables.
If set via export, the environment of the calling process will not be altered.
export [-fn] [name[=word]] ... The supplied names are marked for automatic export to the environment of subsequently executed commands. (https://man7.org/linux/man-pages/man1/bash.1.html)
Child processes do not normally have access to the parent process' environment. (This poses a problem because system() creates a sub-process.)
The source and . built-ins execute the commands in the current shell environment, hence why your script works.
Other commands (executables, non-shell-builtins) are executed by the fork-and-exec mechanism, whereby the executing shell process forks, creating a child process with an identical environment and state. This new child process is the process in which the command is executed. Changes to the environment of that process are not replicated to the parent's environment.
This means that you will not be able to rely on system('...') to modify the environment of the R process, or that of processes spawned by subsequent system() invocations.
In a single invocation to system(), you can construct a command-line that changes the environment of the spawned shell like so:
bash -c 'source ~/.bashrc; use Python-3.4; python --version'
Mind you, ~/.bashrc is not really the best place to put this functionality (might be subjective).
When you call system() it uses /bin/sh, not /bin/bash. sh doesn't read your .bashrc file when it starts up, so it does not know any of the functions you've defined there.
To use the function from your .bashrc, you must get bash to run it instead:
system("bash -c 'use Python-3.4; python --version'")
Edit: placement of closing single quote.

gud-pdb emacs usage and PATH

I'm trying to use gud-pdb for Python debugging within Emacs.
Having an issue that pdb doesn't seem to be searching the PATH when looking for my .py files
I.e., I have a python script in a dir which is on the PATH, I can run this script from anywhere outside of pdb, i.e., from the command line.
But when I try and run it from within pdb it tells me the file doesn't exist.
I'm trying to run pdb against the script in a dir that contains the data to be processed.
I think this is a standard thing to want to do. I successfully do it for gdb and C programs all the time.
Anyone had this issue and know how to fix it?
Given that you're able to run your script outside of Emacs, but not
within, you probably
need
exec-path-from-shell.
This syncs up environment variables (like PATH) between your shell
and Emacs.
Have you tried the realgud package since you are using python?
;;M-x load-library realgud python -m pdb myscript.py
(package-install 'realgud) ;; python debugging in emacs
(defun sdev/init-realgud
(interactive)
(load-library "realgud"))
(sdev/init-realgud 1)

emacs python pdb hang

I have successfully used
M-x pdb
and then type in
python -m pdb myscript.py
and step thru my code before when i have a linux box. Now i have to do all my work in windows. I have downloaded Vincent Goulet's emacs window disbribution and Anaconda2 Python distribution and while all the python shell is working the same M-x pdb step thru my code is not working.
Precisely what happen is that i put in
M-x pdb
Then ask Run pdb (like this):
I try all 3
1) python -m pdb my_script.py
2) python my_script.py
3) my_script.py
i get a new buffer *gud-my_script.py*
in it is
Current directory is c:/User/my_user_name/Documents/python
then it just hang there.
I also try other pdb use case (i.e in script my_script2.py, i wrote)
import pdb; print "hello world1"; pdb.set_trace(); print "line 2"
then just in emacs window command promot run
python my_script2.py
the command promot will not even shows "hello world1" and just freeze there and command prompt won't return
the strange thing is that if i run this NOT in emacs and just in windows command CMD then it will work. i.e. it will print "hello world1" and then drop into debugger.
i did not making any special entry in .emacs after i downloaded Anaconda so to be honestly i don't even know which python mode i am in and why emacs is preventing interaction to show up from pdb.set_trace()
there is similar problem in stack exchange. except i am not doing google app development. Mine is a minimum example.
emacs pdb just hang

IPython uses a different $PATH environment than the shell

I had some problems with calling pip within the IPython REPL, and after a while I noticed that IPython doesn't use the same $PATH environment as my shell.
$ echo $PATH
/Users/jimmy/dev/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin
$ ipython
In [1]: !echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin:/Users/jimmy/dev/anaconda/bin
It does seem to scramble the path order, and I'm not quite sure what's wrong.
I'm using ZSH installed through oh-my-zsh as shell, if it is of help.
This is what sys.path() returns:
['',
'/Users/jimmy/dev/anaconda/bin',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/sparsesvd-0.2.2-py2.7-macosx-10.5-x86_64.egg',
'/Users/jimmy/dev/projects/pyresult',
'/Users/jimmy/dev/work/gavagai/userdata',
'/Users/jimmy/dev/work/gavagai/gavapi',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python27.zip',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-darwin',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-mac',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/plat-mac/lib-scriptpackages',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-tk',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-old',
'/Users/jimmy/dev/anaconda/python.app/Contents/lib/python2.7/lib-dynload',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/runipy-0.1.0-py2.7.egg',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/setuptools-3.6-py2.7.egg',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/PIL',
'/Users/jimmy/dev/anaconda/lib/python2.7/site-packages/IPython/extensions',
'/Users/jimmy/.ipython']
And this is what os.environ['PATH'] returns:
'/Users/jimmy/dev/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin'
Both seem to place it in the correct order.
Grateful for all help.
To summarize and complement #holdenweb's helpful answer, particularly with respect to OS X:
A subshell started from IPython with ! is a non-interactive non-login instance of the user's default shell - even if IPython was started from a different shell.
Behind the scenes, the subshell is started with path/to/default/shell -c ...
To see specifics, run !ps -p $$ && :
echo $SHELL always tells you the default shell - even when run from a different shell.
Initialization files sourced in non-interactive non-login shells:
zsh:: /etc/zshenv and ~/.zshenv
bash: a script pointed to in the $BASH_ENV variable, if defined.
As pointed out, shells load different/additional initialization files depending on whether:
the shell is a login shell or not
an interactive shell or not
Note that a login shell can be interactive or not, and an interactive shell can be a login shell or not.
Thus, in the case at hand, potentially two additional initialization files were loaded in the interactive shell, explaining the difference in behavior between the interactive shell and the subshell created by IPython:
~/.zprofile - if the shell is a login shell - which will be the case if zsh is the default shell (on OS X, all interactive instances of the default shell created in a terminal such as Terminal.app are login shells).
~/.zshrc
Finally, on a related note, note that on OS X the default $PATH for NON-shell processes is:
/usr/bin:/bin:/usr/sbin:/sbin # Note the absence of /usr/local/bin.
and only shells add /usr/local/bin (by default; extensible) to that, via system-wide initialization files (that call /usr/libexec/path_helper):
zsh:
/etc/zshenv
Note: takes effect for ALL zsh instances.
bash (also when invoked as sh), ksh:
/etc/profile
Note: takes effect for LOGIN shells only.
Upshot:
Non-shell apps see only the default $PATH (notably, without /usr/local/bin and other additions made via shell initialization files).
bash/sh and ksh non-interactive non-login shells not launched from a login shell also see only the default $PATH. This happens, for instance, when GUI command-line launchers such as Alfred create shell instances.
zsh is not affected, because /etc/zshenv is read by every zsh instance.
First of all, sys.path has little to do with this; it's just the list of locations in which the Python interpreter can look when importing modules, and does not determine where executable programs are found by the shell. Some elements of the PATH are seen in that list, though, because the interpreter uses the path of its executable to build certain entries on sys.path.
os.environ['PATH'] is, unsurprisingly, the same as the $PATH variable from the environment in which IPython is running. !echo $PATH prints out the $PATH variable from the subshell started by IPython to execute the shell escape (!).
One possible cause is that IPython is executing the shell commands using the OS standard shell which has not been tailored to set its path in the same way that your zsh has. You can confirm this by executing the IPython command !echo $SHELL. Since you confirmed this was not the case then the difference can be accounted for by the differences between a login shell and an interactive shell.
I don't know of a configuration item that will tell IPython to use another shell, but it's possible there is one. As a workaround, just make sure the other shell has a correctly configured path, or that interactive shells also see the environment you require.
See #mklement0's extremely authoritative answer for the whole, gory, messy details.

Debugging python programs in emacs

How do I debug python programs in emacs? I'm using python-mode.el
I've found references suggesting:
import pdb; pdb.set_trace();
but I'm not sure how to use it.
Type M-x cd to change directory to the location of the program you wish to debug.
Type M-x pdb. You'll be prompted with Run pdb (like this): pdb. Enter the name of the program (e.g. test.py).
At the (Pdb) prompt, type help to learn about how to use pdb.
Alternatively, you can put
import pdb
pdb.set_trace()
right inside your program (e.g. test.py). Now type M-x shell to get a shell prompt. When you run your program, you'll be dumped into pdb at the point where pdb.set_trace() is executed.
For me, I needed to replace the default "pdb" with
python -m pdb myscript.py
The realgud package (available from MELPA) supports PDB (among a gazillion other debuggers), and has a host of neat features that Emac's PDB doesn't have.
The one I like best is the shortkeys mode. Once you start debugging a program, you can press n, s, c etc. right in the source window, instead of having to type these commands in the PDB buffer. It also supports Visual-Studio style keybindings with function keys (f10, f11, f5, etc).
After installing RealGUD, you need to run M-x load-feature realgud to load it, and you can start pdb with M-x realgud:pdb.

Categories

Resources