cpython
cpython copied to clipboard
pdb mangles sys.path when run with -P or ._pth
Bug report
When running a script, pdb
indiscriminately replaces sys.path[0]
, which it assumes to be the path where pdb
itself was found, with the path where the script was found. That assumption may not be correct: it is not when the interpreter runs in “safe path” mode due to a -P
command line option or the presence of a ._pth
file. In that case sys.path[0]
may point to the standard library, and overwriting it may break the script’s ability to import standard library modules.
This is easily reproduced in the embeddable package for Windows, which has the standard library in python311.zip, refers to it in sys.path[0]
, and has a python311._pth file, but should also be reproducible (using -P
) on other platforms in any other installation that finds the standard library in sys.path[0]
. (This is not the case in a standard installation for Windows, which has '…\\python311.zip'
in sys.path[0]
, but that file doesn’t actually exist and the standard library is located in files in Lib/
and is found through later entries in sys.path
.)
Steps to reproduce
script.py:
import sys
print(sys.path)
import random
print(random.random())
Actual result
C:\Users\Walther\pdbtest>python-3.11.0-embed-amd64\python.exe -m pdb script.py
> c:\users\walther\pdbtest\script.py(1)<module>()
-> import sys
(Pdb) c
['C:\\Users\\Walther\\pdbtest', 'C:\\Users\\Walther\\pdbtest\\python-3.11.0-embed-amd64']
Traceback (most recent call last):
File "pdb.py", line 1768, in main
File "pdb.py", line 1646, in _run
File "bdb.py", line 597, in run
File "<string>", line 1, in <module>
File "C:\Users\Walther\pdbtest\script.py", line 3, in <module>
import random
ModuleNotFoundError: No module named 'random'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> c:\users\walther\pdbtest\script.py(3)<module>()
-> import random
(Pdb) q
Post mortem debugger finished. The C:\Users\Walther\pdbtest\script.py will be restarted
> c:\users\walther\pdbtest\script.py(1)<module>()
-> import sys
(Pdb) q
Expected result
C:\Users\Walther\pdbtest>python-3.11.0-embed-amd64\python.exe -m pdb script.py
> c:\users\walther\pdbtest\script.py(1)<module>()
-> import sys
(Pdb) c
['C:\\Users\\Walther\\pdbtest\\python-3.11.0-embed-amd64\\python311.zip', 'C:\\Users\\Walther\\pdbtest\\python-3.11.0-embed-amd64']
0.6351821708383135
The program finished and will be restarted
> c:\users\walther\pdbtest\script.py(1)<module>()
-> import sys
(Pdb) q
It seems to me this could be fixed as follows (which is what I used to get the “expected result”), or maybe by comparing sys.path[0]
with __file__
to check the assumption directly:
--- pdb-orig.py 2022-11-11 10:51:02.717413700 +0100
+++ pdb.py 2022-11-11 10:10:19.737092700 +0100
@@ -147,7 +147,8 @@
sys.exit(1)
# Replace pdb's dir with script's dir in front of module search path.
- sys.path[0] = os.path.dirname(self)
+ if not (hasattr(sys.flags, 'safe_path') and sys.flags.safe_path):
+ sys.path[0] = os.path.dirname(self)
@property
def filename(self):
Any opinions, should I make a PR with that?
Your environment
- CPython versions tested on: 3.11.0
- Operating system and architecture: Windows 10+11 AMD64+ARM64 (but shouldn’t matter)