Python 3.8 scripts suddenly won't run, but Python commands run fine when invoked directly
I am utterly baffled and mystified. I have been happily coding and running Python scripts from the terminal (and also running the Python interpreter). I went to bed a happy user of Python, but suddenly I cannot run any Python script from the shell.
hello.py contains:
#!/usr/bin/python3
print('Hello world!')Yet suddenly:
% ./hello.py
./hello.py: 1: #!/usr/bin/python3: not found
./hello.py: 2: Syntax error: word unexpected (expecting ")")But
% python3 hello.py
Hello world!
% python hello.py
Hello world!What. The. Zarking. Fardwarks.
ls -la hello.py shows:
-rwxrwxr-x 1 Lexible Lexible 44 May 25 08:35 hello.pyPer two requests by @Kulfy
% file -k hello.py
hello.py: Python script text executable\012- a /usr/bin/python3 script, UTF-8 Unicode (with BOM) text executable
% cat -e hello.py
M-oM-;M-?#!/usr/bin/python3$
print('Hello world!')$ls -la /usr/bin/python3* shows:
lrwxrwxrwx 1 root root 9 Mar 13 05:20 /usr/bin/python3 -> python3.8
-rwxr-xr-x 1 root root 5457536 Apr 27 08:53 /usr/bin/python3.8
lrwxrwxrwx 1 root root 33 Apr 27 08:53 /usr/bin/python3.8-config -> x86_64-linux-gnu-python3.8-config
lrwxrwxrwx 1 root root 16 Mar 13 05:20 /usr/bin/python3-config -> python3.8-config
-rwxr-xr-x 1 root root 384 Mar 27 19:39 /usr/bin/python3-futurize
-rwxr-xr-x 1 root root 388 Mar 27 19:39 /usr/bin/python3-pasteurizeFor giggles...
% which python
/usr/bin/python
% which python3
/usr/bin/python3Even...
% python3
Python 3.8.2 (default, Apr 27 2020, 15:53:34)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('Hello world!')
Hello world!
>>>PS: I am using Ubuntu 20.04 (Focal Fossa). I have tried rebooting, and sudo apt install -f --reinstall python3 python3.8 python3-minimal python3.8-minimal libpython3.8-minimal all to no avail.
2 Answers
Since you are able to run the script using python3 hello.py, it is evident that the issue isn't with the Python installation or the symlinks. Instead the issue is with the script itself.
The shell (here, zsh) didn't really recognize the shebang as such because of some alien characters before #. It tried to execute the whole script with the default shell/interpreter, thus producing errors.
You can use the -e option of cat to check the actual contents of the script. -e is basically the combination of v and E. v uses ^ and M- notation, and E displays $ at the end of each line.
After observing the output of cat -e hello.py, it seems the script contains a byte order mark near its shebang/hashbang which may have been inserted by some Windows software. This prevented the script from actually loading the Python interpreter, so it instead got executed by zsh, thus causing the error.
You can remove BOMs and other DOS-specific characters using dos2unix.
dos2unix hello.py # Install using `sudo apt install dos2unix` (if not already installed)dos2unix will take care of all Windows/DOS type characters/line endings and convert them to Unix-like ones.
Or you can also use sed to remove BOMs. Since BOMs were present in UTF-8, their hexadecimal representation is EF BB BF.
sed -i '1s/^\xEF\xBB\xBF//' hello.py 7 With gracious help from @Kulfy the problem seems to be some unrenderable bytes preceding the shebang in my scripts! Specifically, bytes EF BB BF preceded the bytes 23 21 which should be the start of the script(s).
How that byte order mark got there is a mystery, but at least now:
./hello.py
Hello world! 1