It seems that you're using an outdated browser. Some things may not work as they should (or don't work at all).
We suggest you upgrade newer and better browser like: Chrome, Firefox, Internet Explorer or Opera

×
avatar
Kalanyr: Just for the sake of consistency does your suggestion still work if it's altered too:

if False:
#Please start this script with a python interpreter: python /path/to/gogrepoc.py
pass

It just feels cleaner to avoid having a functional python call inside a code path that's explicitly not to be executed.
No, won't work, reason: that's no "unexpected token" for the shell, it's a comment in both programming languages, and therefore ignored by both. The trick here is to have something causing a fatal syntax error in the Shell, but not in Python. Because the valid "print" line is never reached, I've suggested the "comment block" around this construction. You obviously can't do there something being "illegal" in Python, if you do so, the script will fail in normal operation.

Letting the shell reach the "import" commands is by far worse than this imperfect solution. An average user having Imagemagick installed would end up with a "useless mouse pointer"; to avoid a reboot or killing the whole X server, one must open a shell by keyboard, avoiding the mouse entirely, realise what's happening, and either kill a series of "imports" one after the other, or their parent shell and the one leftover "import". That's what happened to me.
avatar
phaolo: Couldn't the script just check if python is installed? Like in windows:
python --version 3>NUL
No, that's not the problem! The error occurs regardless of Python being installed or not.

As I explained (deliberately in detail) above in this thread, Linux won't ever rely on file name extensions (".py" here) when determining the programme to run/open some file with.

There's a more advanced similar mechanism in KDE, where you can assign MIME types to an application, causing some KDE (and ONLY KDE) programmes to open the file with the assigned application, when "mouse clicked" on the name. This, however, would also fail, because the file type is determined by looking at the contents at the file's beginning. This is by far better than the Windows approach under most circumstances, but not perfect.

Our particular script is "recognised" as follows:
----8<--------------------------
$ file /usr/local/games/gogrepoc.py
/usr/local/games/gogrepoc.py: Objective-C source, ASCII text, with very long lines, with CRLF line terminators
----8<--------------------------
So this would probably open it up with a programming editor for most users, that's OK, therefore I suggested the BIG comment near the start telling you to use Python instead.

avatar
phaolo: Also, remember you can shorten it to: py
Less readable, I'd avoid such things. You're not writing for fellow Python experts.
Post edited March 31, 2025 by ChFra
Hello again,

you might have wondered, what the shell is complaining about in those 2 lines:
---------8<---------------------------------------------------------
/usr/local/games/gogrepoc.py: line 2: $'\r': command not found
/usr/local/games/gogrepoc.py: line 6: $'\r': command not found
---------8<---------------------------------------------------------
These lines are empty in the script.

The reason is the script being formatted with DOS/Windows line endings "CR " followed by "LF".
While this is the "historycally correct translation" of old typewriter functionality, it wastes space (one byte per line), so Unixes use "LF" only and (old) Macintoshes "CR" only.

CR = "carriage return" : move the "print head" back to the leftmost position.
LF = "line feed": transport the paper sheet one line further.

The Unix style shells all expect "LF" only line endings, so they fail non-fatally, interpreting the invisible "CR" bytes as an unknown command ("\r" is the C-style representation from the "printf" function).

Python fortunately doesn't care about the line ending type used.

My opinion on this is that the script should use the Windows style, as it currently does, because many Windows text editors, most notably the native "notepad.exe", show Unix style text files as one huge line, breaking everything on saving the file after changing some text.

However, to avoid the irritating messages shown above, I suggest to remove tose 2 blank lines. This makes it ugly, but from a programmer's perspective only, who can handle this.

Without the lines, the output when interpreted by a "normal" Unix style shell is as follows:
--------8<---------------------------------------
from: too many arguments
from: too many arguments
from: too many arguments
/usr/local/games/gogrepoc.py: line 10: syntax error near unexpected token `"Please start this script with a python interpreter: python /path/to/gogrepoc.py"'
'usr/local/games/gogrepoc.py: line 10: ` print("Please start this script with a python interpreter: python /path/to/gogrepoc.py")
--------8<---------------------------------------
(5 lines in total, the GOG forum software breaks that because of the line length.)

That's probably the best we can achieve, since the 3 "from __future__ import" lines must not be preceded by any other Python code.

So I suggest the following code for the file's start:
--------8<---------------------------------------
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
# The following code block between #START# and #END#
# generates an error message if this script is called as a shell script.
# Using a "shebang" instead would fail on Windows.
#START#
if False:
print("Please start this script with a python interpreter: python /path/to/gogrepoc.py")
#END#

__appname__ = 'gogrepoc.py'
[…]
--------8<---------------------------------------

I've now tested the version above with the following shells:
– Debian Almquist Shell (dash): now default on Debian and derivatives)
– Bourne Again Shell (bash): most widely used on Linux
– MirBSD Korn Shell (mksh)
– Zsh: default on some "more exotic" Linux distributions (GRML)
– BSD C-Shell (csh)
– Busybox Ash (busybox called as "ash" or "busybox ash"): default on most "embedded" Linux devices

All of them except the last 2 give the output above with the text information printed out.

csh:
--------8<---------------------------------------
from: too many arguments
from: too many arguments
from: too many arguments
if: Expression Syntax.
--------8<---------------------------------------

Busybox:
--------8<---------------------------------------
from: too many arguments
from: too many arguments
from: too many arguments
/usr/local/games/gogrepoc.py: line 10: syntax error: unexpected word (expecting ")")
--------8<---------------------------------------

Those latter 2 are not what novice users would encounter on their desktop computers, the important point is that all those shells reliably abort execution before anything "evil" can happen.
Post edited March 31, 2025 by ChFra
avatar
Kalanyr: Just for the sake of consistency does your suggestion still work if it's altered too:

if False:
#Please start this script with a python interpreter: python /path/to/gogrepoc.py
pass

It just feels cleaner to avoid having a functional python call inside a code path that's explicitly not to be executed.
avatar
ChFra: No, won't work, reason: that's no "unexpected token" for the shell, it's a comment in both programming languages, and therefore ignored by both. The trick here is to have something causing a fatal syntax error in the Shell, but not in Python. Because the valid "print" line is never reached, I've suggested the "comment block" around this construction. You obviously can't do there something being "illegal" in Python, if you do so, the script will fail in normal operation.

Letting the shell reach the "import" commands is by far worse than this imperfect solution. An average user having Imagemagick installed would end up with a "useless mouse pointer"; to avoid a reboot or killing the whole X server, one must open a shell by keyboard, avoiding the mouse entirely, realise what's happening, and either kill a series of "imports" one after the other, or their parent shell and the one leftover "import". That's what happened to me.
Hmm what about:

if False:
pass #Please start this script with a python interpreter: python /path/to/gogrepoc.py

Or does the shell script interpreter strip comments before any processing at all ? So that it just reads that as

if False
pass

?
I'm a (part-time) programmer but not qualified enough to comment one way or the other.

What ChFra is suggesting is sort of what polyglot programs usually use: one source file that can be compiled/interpreted in two or more different languages (in polyglot programs: to produce the same output).

I think phaolo has more of the right idea, surely detecting whether a python instance is on windows is a solved problem already. There must be a better way than trying to write a hybrid python/bash script.
avatar
Kalanyr: Hmm what about:

if False:
pass #Please start this script with a python interpreter: python /path/to/gogrepoc.py
From what I remember from looking it up last night bash will throw a syntax error csh will treat the midline # as a comment
Post edited March 31, 2025 by lupineshadow
avatar
lupineshadow: I'm a (part-time) programmer but not qualified enough to comment one way or the other.

What ChFra is suggesting is sort of what polyglot programs usually use: one source file that can be compiled/interpreted in two or more different languages (in polyglot programs: to produce the same output).

I think phaolo has more of the right idea, surely detecting whether a python instance is on windows is a solved problem already. There must be a better way than trying to write a hybrid python/bash script.
avatar
Kalanyr: Hmm what about:

if False:
pass #Please start this script with a python interpreter: python /path/to/gogrepoc.py
avatar
lupineshadow: From what I remember from looking it up last night bash will throw a syntax error csh will treat the midline # as a comment
Detecting if a python script is on Windows is certainly a solved problem, detecting if a python script is on Windows before a shebang would be executed on Linux or by py on Windows (the first line of the the file) is a bit tricker. The simplest way would probably be to provide a shebang wrapper script for Linux that just executes the main script really but that's also kinda messy and confusing to a non-programmer.
avatar
Kalanyr: The simplest way would probably be to provide a shebang wrapper script for Linux that just executes the main script really but that's also kinda messy and confusing to a non-programmer.
I love your script but pure and perfect it is not :) I already have to comment out all the preallocation stuff as mentioned previously and some command line arguments that weren't passed to the functions I had to adjust but I'm not complaining, I really appreciate all the time you put into this python script because you save a lot of people a lot of time and it generally works.

It reminds me of the quote about perfect being the enemy of the good.

But quines/polyglot programs are not programming they are programming contest quirks.

Better to have separate releases, or detail in the readme the different ways of executing the program, or some other way. Some cleaner way :) (edit: assuming there is not some standard way already established)
Post edited March 31, 2025 by lupineshadow
avatar
Kalanyr: Hmm what about:

if False:
pass #Please start this script with a python interpreter: python /path/to/gogrepoc.py
Doesn't work:
----8<--------------------------------------------------
from: too many arguments
from: too many arguments
from: too many arguments
/usr/local/games/gogrepoc.py: line 54: syntax error near unexpected token `"Your Python version is not supported, please update to 2.7+"'
'usr/local/games/gogrepoc.py: line 54: ` print("Your Python version is not supported, please update to 2.7+" )
----8<--------------------------------------------------
This will find the "unexpected token" when encountering the "forbidden" print after the next 2 "if" statements.
avatar
Kalanyr: Or does the shell script interpreter strip comments before any processing at all ? So that it just reads that as

if False
pass

?
I think so; comments are entirely ignored, i.e. everything after a # is "thrown away".

Tested in Dash, Bash, and Csh this time, the last one doing exactly the same as before, not printing out the offending line like Bourne/Korn type shells do.
I don't know too much about programming, but this is curious.
I'm writing suggestions just for fun, sorry if they're absurd.

If the only issue on Windows is the error message about the shebang..
'#!' is not recognized as an internal or external command, operable program or batch file.

..why not just redirect it?
What happens in Linux tho, can we trick it? XD
#! shebang blabla>NULL 2>&1

(pls try it only if you know it won't make the OS explode lol)
Post edited March 31, 2025 by phaolo
In this case I strictly prefer simplicity over beauty. If I'm not mistaken, it is impossible to solve the problem by distributing just ONE file for all systems whithout doing something "ugly" like I suggested.

Different files for different platforms or some "wrapper(s)" would easily solve that, but at the cost of being even more complicated to install and use it correctly for the average user. Besides, a wrapper for Linux STILL does not prevent anybody from executing the python file "standalone". To make it easy and fool-proof, you'll have to package it, resulting in at least 4 "mainstream" versions: Linux .deb & .rpm, Windows, OS X.
avatar
ChFra: In this case I strictly prefer simplicity over beauty.
Python has a whole thing about that - except simple > beautiful is not one of the things mentioned. The fact that you expanded your testing to include csh...how about fish - also a popular shell? How about non-standard shells?

Polyglot programs are one of the most hackiest solutions ever. If you're on a salary and your job is to deliver x no matter what then fair enough.

Otherwise the cost is greater than the gain.

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
Post edited March 31, 2025 by lupineshadow
avatar
phaolo: I don't know too much about programming, but this is curious.
I'm writing suggestions just for fun, sorry if they're absurd.

If the only issue on Windows is the error message about the shebang..
'#!' is not recognized as an internal or external command, operable program or batch file.

..why not just redirect it?
What happens in Linux tho, can we trick it? XD
#! shebang blabla>NULL 2>&1

(pls try it only if you know it won't make the OS explode lol)
No, the problem on Windows is that a near identical syntax is used to indicate to py what version of python it should execute the script in, and you can get weird results from it trying to parse a Linux shebang ( and vice versa ), it actually works fine on Windows if you don't have py installed, but having py installed is relatively common ( even some people who don't realize it will have it installed due to semi-standalone Python installs from stuff like Anaconda ) , python itself ignores the shebang because it starting with # means that python treats it as a comment.
avatar
ChFra: In this case I strictly prefer simplicity over beauty.
avatar
lupineshadow: Python has a whole thing about that - except simple > beautiful is not one of the things mentioned. The fact that you expanded your testing to include csh...how about fish - also a popular shell? How about non-standard shells?
I expanded testing simply to those shells already installed on the machine I'm runnig this script on.

Installed "fish", result:
-----8<-------------------------------
fish: Failed to execute process '/usr/local/games/gogrepoc.py'. Reason:
exec: Fehler im Format der Programmdatei
fish: The file '/usr/local/games/gogrepoc.py' is marked as an executable but could not be run by the operating system.
-----8<-------------------------------

Fish starts it like an ELF file. It won't run this way, thus it has no side effects such as the execution of words like "import" being "seen" as valid executable file names by the shell.

I think people using "exotic" shells can handle the situation that the text line isn't displayed. The important thing is that it consistently fails, before any "random things" are started (which "things" could even change in future versions).

You forget that all the "good" and "clean" solutions cannot prevent the script from being interpreted by a shell, if started so by the user, except when using a "shebang" which in turn breaks things for many Windows users. Most "gamers" use Windows, and know little about the "inner workings" of their computers, so the "shebang" is not an optiion.

"Unhacky" approaches, however, don't prevent the user from doing a "chmod +x gogrepoc.py" and trying to start that afterwards, causing the nuisance I described earlier, and possibly worse things after some changes in future versions.
You can chmod +x the works of Shakespeare and then ./kinglear and it might have undefined behaviour but as far as I know Shakespeare didn't include rm -rf in any of his neologisms so maybe it's ok.

I did the same as you incidentally and also got the Imagemagick screenshot crosshair and it freaked me out but otherwise there was no side-effects.

I imagine detrimental side-effects are as difficult to achieve as preventative guards.
So I tried moving the manifest file, and I ended up getting the no such file error again. It would crash whenever it got to a point where it wanted to save manifest.

I'm currrently trying to dropbox version you posted to attempt to fix this issue, and it made it past the saving manifest part just fine.

Hoppefully I won't have to update with more issues.

Thanks!