Python script is in a certain folder. At the beginning of the file is written

#!/usr/bin/env python 

The command chmod u+x ./filename.py was also executed when trying to start from a terminal ./filename.py replies:

No such file or directory

ls -lh :

 -rwx--x--x 1 User User 9.8K Sep 27 16:01 filename.py 

The output of which python :

 /usr/bin/python 

Were tried out of despair as well

 #!/usr/bin/python python #!/usr/bin/python 
  • please look at the second and third paragraphs from this answer . - aleksandr barakin
  • apparently no 00000000 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 70 | #! / usr / bin / env p | 00000010 79 74 68 6f 6e 0d 0a 23 2d 2a 2d 20 63 6f 64 69 | ython .. # - - codi | 00000020 6e 67 3a 20 55 54 46 2d 38 20 2d 2a 2d 0d 0a 69 | ng: UTF-8 - - - Igor Vasyutin
  • 2
    0d 0a is cr + lf (it is also \r\n ). maybe it’s worth replacing line feeds with “unix” \n ? This can be done, for example, using the $ dos2unix файл . - aleksandr barakin
  • thank you very much. helped - Igor Vasyutin
  • designed in the form of a detailed response. mark it, please, accepted ("tick" to the left of the answer). - aleksandr barakin

2 answers 2

tl; dr : see. Conclusions below


To understand where the empty file name comes from (to the left of : in the error message):

 >>> import os >>> os.system('./hi.py') : No such file or directory 32512 

You can invoke the command directly without a shell (such as bash):

 >>> from subprocess import Popen, PIPE >>> Popen('./hi.py', stdout=PIPE, stderr=PIPE).communicate() (b'', b'/usr/bin/env: python\r: No such file or directory\n') 

the result says that b'\r' recognized as part of the command name. On POSIX systems, the file name can be an arbitrary sequence of bytes (except zero b'\0' and slash b'/' ). If you create an executable file in the PATH, which is named b'python\r' :

 >>> os.symlink('/usr/bin/python', os.path.expanduser('~/bin/python\r')) 

then the error disappears:

 >>> os.system('./hi.py') hi! 0 

where hi.py simple Python executable script with Windows endings of strings:

 >>> open('hi.py', 'wb').write(b'#!/usr/bin/env python\r\nprint("hi!")') >>> os.chmod('hi.py', 0b111101101) # rwxr-xr-x 

The command name is not visible in the first example, because b'\r' in the terminal moves the cursor to the beginning of the line:

 >>> print('abc\r12') 12c 

that is, the letters ab are clogged with 12 in this example. The example demonstrates the traditional behavior for CR (carriage return).

Python itself supports the universal mode of new lines and therefore works with '\r\n' and on Unix:

 >>> os.unlink(os.path.expanduser('~/bin/python\r')) >>> os.system('python ./hi.py') hi! 0 

#! -string (shebang) does not recognize python , and not even bash , but the kernel of the operating system (Linux, for example). By default, modern versions of Unix ignore the horizontal space (space b' ' and tab b'\t' ) at the end of #! -strings:

 >>> import string >>> for ws in string.whitespace: ... with open('space[%X].py' % ord(ws), 'w') as f: ... f.write('#!/usr/bin/env python%s\nprint("%X")' % (ws, ord(ws))) >>> from glob import glob >>> for cmd in glob('./spac*.py'): ... os.chmod(cmd, 0b111101101) ... Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() ... (b'', b'/usr/bin/env: python\r: No such file or directory\n') (b'20\n', b'') (b'A\n', b'') (b'', b'/usr/bin/env: python\x0b: No such file or directory\n') (b'9\n', b'') (b'', b'/usr/bin/env: python\x0c: No such file or directory\n') 

That is, the command works for ' \n\t' and does not work for '\r\v\f' .


If you want to run the script directly (without explicitly specifying the interpreter), then you should use Unix line endings, as suggested by @alexander barakin :

 >>> data = open('./hi.py', 'rb').read() >>> open('./hi.py', 'wb').write(data.replace(b'\r\n', b'\n')) 34 >>> os.system('./hi.py') hi! 0 

Version control systems such as Mercurial (hg), git probably have options that will help replace the new lines of the current operating system with \n for .py files automatically if you cannot use an editor that supports \n directly .

If the author of the command implemented on Python works only on Windows and does not want to complicate the process, then by creating setup.py , which defines setuptools' entry_points , you can automatically support different systems (if there are no other incompatibilities) :

 from setuptools import setup setup(name='program', version='1.2.5', description='', long_description='', author='', author_email='', url='', license='', py_modules=['program'], entry_points={ 'console_scripts': ['program=program:main'] } ) 

where the program.py file, for example, could be created on Windows:

 >>> open('program.py', 'wb').write(b'#!/usr/bin/env python\r\ndef main():\r\n print("hi!")\r\n') 52 

The installation creates scripts with the correct #! - string on Unix systems and corresponding .exe files on Windows:

 >>> import subprocess >>> import sys >>> subprocess.call([sys.executable] + '-m pip install -e .'.split()) Obtaining file:///tmp/prj Installing collected packages: program Running setup.py develop for program Successfully installed program-1.2.5 0 >>> subprocess.call('program') hi! 0 

Direct reading of a machine-generated file confirms that '\n' used on Unix ( docker run -v $PWD:/tmp/prj -it --rm python ) system:

 >>> import shutil >>> open(shutil.which('program'), 'rb').readline() b'#!/usr/local/bin/python3\n' 

findings

  • '\r' in #! -string is considered as part of the command name ( b'python\r' ) on some systems, which causes the error: "No such file or directory" when trying to run a script

  • some terminals, encountering '\r' in the output of the program, move the cursor to the beginning of the line, so the file name in the error message (the part to the left of the colon) seems empty (the message text is printed on top of it)

  • it is not clear why the Linux kernel does not ignore '\r' at the end of #! -strings, as it does for spaces and tabs. Perhaps this choice has been made to help notice that the script has incompatible line terminations (which may indicate other problems with portability in the program)

  • The preferred way to work around this problem is to use an editor that supports '\n' on Windows. Or, if development is carried out exclusively on Windows, then the creation of setup.py with setuptools' entry_points as shown above, so that during the installation, the correct wrapper scripts for the platform are generated automatically.

    Algorithm for finding the possible causes of such an error

    1. perhaps there are bom- s at the beginning of the file, or other unreadable characters were “crammed” into the first lines, which can be found by browsing the file by-by-by, for example:

       $ hexdump -C файл | less 

      about removing bom- s: How to remove a BOM from a file?

    2. perhaps, at the beginning of the file there are translations of the lines of the “ wrong system ” (for unix-like, they must be \n , it is lf , that is, linefeed , hexadecimal code 0x0a ), or a mixture of them.

      • How to check - see the previous paragraph.

      • you can fix the “dosovsky” cr + lf ( \r\n , hexadecimal code 0x0d 0x0a ), for example, using the dos2unix dos2unix (from the package of the same name):

         $ dos2unix файл 
      • You can fix the "Makovsky" cr ( \r , hexadecimal code 0x0d ), for example, using the mac2unix mac2unix (from the same package as above):

         $ mac2unix файл