Reputation: 386
I've written a little batch file (Windows 8.1) to start my script directly in IDLE:
START "" pythonw.exe "C:\Program Files (x86)\Python36-32\Lib\idlelib\idle.py" -r my_script.py
The script contains the line
my_dir = os.path.split(__file__)[0]
which produces a name error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "my_script.py", line 245, in out_file_dia
my_dir = os.path.split(__file__)[0]
NameError: name '__file__' is not defined
If I open IDLE first and then start the script, it works fine. Why is
__file__
not defined in this situation?
Upvotes: 0
Views: 386
Reputation: 19144
In interactive mode, the input 'file' is the stream of statements entered by the user, so __file__
is left unset. If there is a PYTHONSTARTUP file, __file__
is set to that filename while the file is run, then unset before the first >>>
prompt. Currently, IDLE does not do this when running user code in a separate process, which is now the normal mode.
I opened https://bugs.python.org/issue32984 to fix this. I will try to remember to report here when it is.
When IDLE is started with -n, to use the old deprecated mode in which user code is executed in the IDLE GUI process, startup files and interactive input see __file__
set to an idlelib file. Both are wrong but will not be fixed.
EDIT: PR-5981, which works for me on Windows, modifies pyshell.execfile to begin as follows:
def execfile(self, filename, source=None): # currently line 633
"Execute an existing file"
if source is None:
with tokenize.open(filename) as fp:
source = fp.read()
if use_subprocess:
source = (f"__file__ = r'''{os.path.abspath(filename)}'''\n"
+ source + "\ndel __file__")
The last 3 lines are new. uwain12345, adding them should solve your problem. If not, I would like to know.
EDIT 2: tweek replacement code to allow for ' in startup file name.
Note: f strings are new in 3.6. For older Pythons, replace the source
line with
filename = os.path.abspath(filename)
source = ("__file__ = r'''{}'''\n".format(filename)
Upvotes: 2