5

Situation: My Python script has a line of code that copies itself to another directory

shutil.copyfile(os.path.abspath(__file__), newPath)

Problem: The script is then compiled into an EXE and ran. The error given is as follows:

FileNotFoundError: No such file or Directory: "C:\Path\To\EXE\script.py"

As you can see, the EXE is looking for the .py version of itself (i.e. uncompiled version)

Question: Is there another Python command that can still let the executable find itself and not the .py version of itself?

Additional information: I was going to try to just replace .py with .exe and see if it works -- it would have if not for the program to fail if I change the name of the executable.

C:\ > script.exe
#Works as expected

C:\ > ren script.exe program.exe
C:\ > program.exe
FileNotFoundError: No such file or directory: "C:\script.py"
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Timothy Wong
  • 689
  • 3
  • 9
  • 28

2 Answers2

11

I was stuck in this problem too. Finally I found the solution from the official document.


Solution:

Use sys.argv[0] or sys.executable to access the real path of the executed file.


Explanation:

This is because your executable is a bundle environment. In this environment, all the __file__ constants are relative paths relative to a virtual directory (actually the directory where the initial entrance file lies in).

As instructed by the document, you can access the absolute by using sys.argv[0] or sys.executable, as they are pointing to the actually executed command. So in a bundle environment, you call script.exe, and sys.executable will be script.exe. While in a running live environment, you call python script.path, and sys.executable will be python.exe.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
Cosmo
  • 836
  • 1
  • 12
  • 27
  • I found it out recently too, but didn't update the answer. Thanks anyway! – Timothy Wong Nov 29 '18 at 14:48
  • I found that `sys.executable` works only on .exe files but `sys.argv[0]` works when I run the script like this `python script.py` and when I build the script to exe and run it using cmd. This is how I reference things now: `os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'Resources')` – ZiyadCodes Nov 02 '22 at 17:46
2

Try the following:

from os.path import abspath, splitext
fromfile_without_ext, ext = splitext(abspath(__file__))
shutil.copyfile(fromfile_without_ext + '.exe', newPath)

(Did not test it, but should work...)

Dick Kniep
  • 518
  • 4
  • 11
  • I'll try it when I get to it. Thanks – Timothy Wong Jul 19 '18 at 07:38
  • 2
    That's not the correct way. Because the `__file__` const will always be a relative path to the entrance script (e.g. `script.py`) wherever and however you call the executable. The correct way is to use `sys.argv[0]` or `sys.executable`. – Cosmo Nov 28 '18 at 02:37