Python 2.0 script won't run under MATE 20.04

Let me first say that I am not a programmer so I'm unable to update my Python script. Now for my problem: I have a Python 2.0 script file, which generates a graphical interface for running programs under DosBox. Since updating to MATE 20.04 it no longer works. Does anyone know how I can get Python 2.0 back onto my machine?
Thanks,
Jim

LATER: I tried converting my file using the converter at https://pythonconverter.com/
but my script file was written using python and pygtk, so I'm guessing some part in the pygtk is not converting properly.

I think you can sudo apt install python-minimal , verify that you have python 2.7, and test.

Tried to install python-minimal, but ran into the following error message

[email protected]:~$ sudo apt install python-minimal
[sudo] password for jim: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package python-minimal is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
  python2-minimal:i386 python2-minimal

E: Package 'python-minimal' has no installation candidate
[email protected]:~$ sudo apt install python2-minimal:i386 python2-minimal
Reading package lists... Done
Building dependency tree       
Reading state information... Done
python2-minimal is already the newest version (2.7.17-2ubuntu4).
python2-minimal set to manually installed.
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 python2-minimal : Recommends: python2 but it is not going to be installed
                   Conflicts: python2-minimal:i386 but 2.7.17-2ubuntu4 is to be installed
 python2-minimal:i386 : Depends: python2.7-minimal:i386 (>= 2.7.17~rc1-1~) but it is not going to be installed
                        Recommends: python2:i386 but it is not going to be installed
                        Conflicts: python2-minimal but 2.7.17-2ubuntu4 is to be installed
E: Unable to correct problems, you have held broken packages.
[email protected]:~$

It seems that I have python 2.7 installed, but the held broken packages do not show up when I run sudo apt autoremove.

what does ls -l /usr/bin/python* give you ...

lrwxrwxrwx 1 root root       7 Apr 15 05:45 /usr/bin/python -> python2
lrwxrwxrwx 1 root root       9 Mar 13 07:31 /usr/bin/python2 -> python2.7
-rwxr-xr-x 1 root root 3694632 Apr  7 07:05 /usr/bin/python2.7
lrwxrwxrwx 1 root root       9 Mar 13 07:20 /usr/bin/python3 -> python3.8
-rwxr-xr-x 1 root root 5457568 Mar 13 05:14 /usr/bin/python3.8
-rwxr-xr-x 1 root root     384 Mar 27 21:39 /usr/bin/python3-futurize
-rwxr-xr-x 1 root root     388 Mar 27 21:39 /usr/bin/python3-pasteurize

I got exactly the same output.

Try changing the shebang at the top of the Python file to:

#!/usr/bin/python2

Python 2 has reached end of life, so distributions are increasingly pointing /usr/bin/python to the newer /usr/bin/python3.

You may need to install additional python- packages for your script. For PyGTK, I think it's python-gi?

1 Like

The first line of my Python file was
#!/usr/bin/env python

I tried changing it to both #!/usr/bin/env python2 and #!/usr/bin/python2
I also installed python-gi
Still having same problem.

What is the output when you run your script?

Not sure what you mean by output, but before upgrading to 20.04 it produced a graphical interface where I could select which DOS program I wanted to run with the cursor.
Now when I double-click the launcher, it temporarily produces an icon in the taskbar which disappears after a few seconds.

I meant by running it in the Terminal (with CTRL+ALT+T), drag and drop the script file and then press ENTER to run. This should show a traceback with some indications of the error.

#!/usr/bin/env python2

# Author: Panayotis Katsaloulis
# email:  http://www.panayotis.com
# 
# Frontend of DOSBox emulator, written in python and pygtk

# Copyright (C) 2003 Panayotis Katsaloulis
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# or check http://www.gnu.org


import gtk,gobject,os

class Base:
	def __init__(self):

		self.opt_fullscreen = ""
		self.opt_exit = ""
		self.gamelist = []
		self.dosboxpath = "/usr/bin/dosbox"
		#Create main window
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		
		# Create executable chooser
		self.exec_hbox = gtk.HBox()
		self.browse = gtk.Button("Browse")
		self.executable = gtk.Entry(0)
		self.execlabel = gtk.Label("Executable")
		self.exec_hbox.pack_start(self.execlabel, gtk.FALSE, gtk.FALSE)
		self.exec_hbox.pack_start(self.executable, gtk.TRUE, gtk.TRUE)
		self.exec_hbox.pack_start(self.browse, gtk.FALSE, gtk.FALSE)
		
		self.profbox = gtk.HBox()
		self.store_b = gtk.Button ("Store")
		self.delete_b = gtk.Button ("Delete")
		self.profbox.pack_start(self.store_b)
		self.profbox.pack_start(self.delete_b)

		# Browser creation
		self.filesel = gtk.FileSelection ("Please provive with the Executable filename")

		# DOSBOX options
		self.optbox = gtk.VBox()
		self.fullscreen = gtk.CheckButton ("Full screen mode")
		self.exitb = gtk.CheckButton ("Exit DOS mode after program fiishes")
		self.execb = gtk.Button ("Execute Game")
		self.name_label = gtk.Label ("Name of the game")
		self.gname = gtk.Entry(0)
		self.separator = gtk.HSeparator()
		self.optbox.pack_start(self.name_label, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(self.gname, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(self.separator, gtk.FALSE, gtk.FALSE, 5)
		self.optbox.pack_start(self.exec_hbox, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(self.fullscreen, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(self.exitb, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(self.execb, gtk.FALSE, gtk.FALSE)
		self.optbox.pack_start(gtk.Label(" "), gtk.TRUE, gtk.TRUE)
		self.optbox.pack_end(self.profbox, gtk.FALSE, gtk.FALSE)
		
		# Games list
		self.scr_window = gtk.ScrolledWindow()
		self.scr_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.model = gtk.ListStore(gobject.TYPE_STRING)
		self.tree = gtk.TreeView(self.model)
		self.selection = self.tree.get_selection()
		cell = gtk.CellRendererText()
		self.tree.show()
		self.scr_window.add_with_viewport (self.tree)
		self.scr_window.show()
		column = gtk.TreeViewColumn("Game Presets", cell, text=0)
		self.tree.append_column(column)
		self.scr_window.set_size_request(200, 400)
		

		# Pack *all* remaining components
		self.hpane = gtk.HPaned()
		self.hpane.add1(self.scr_window)
		self.hpane.add2(self.optbox)
		self.window.add(self.hpane)
		self.window.set_size_request(620, 400)

		# Make all objects visible
		self.exec_hbox.show()
		self.browse.show()
		self.executable.show()
		self.execlabel.show()
		self.store_b.show()
		self.delete_b.show()
		self.name_label.show()
		self.gname.show()
		self.separator.show()
		self.profbox.show()
		self.optbox.show()
		self.fullscreen.show()
		self.exitb.show()
		self.execb.show()
		self.hpane.show()
		self.window.show()

		# Handle GUI events
		self.window.connect("delete_event", self.delete_event)
		self.window.connect("destroy", self.destroy)
		self.execb.connect("clicked", self.exec_game)
		self.browse.connect("clicked", self.browse_filename)
		self.store_b.connect("clicked", self.add_profile)
		self.delete_b.connect("clicked", self.delete_profile)
		self.fullscreen.connect("toggled", self.full_toggle)
		self.exitb.connect("toggled", self.dos_toggle)
		self.filesel.ok_button.connect("clicked", self.browse_ok)
		self.filesel.cancel_button.connect("clicked", self.browse_cancel, "cancel")
		self.filesel.connect("delete_event", self.browse_ignore)
		self.selection.connect("changed", self.profile_select)
	
		self.restore_profiles()

		gtk.main()

		
	def delete_event(self, widget, event, data=None):
		return gtk.FALSE
		
	def destroy(self, widget, data=None):
		self.store_profiles()
		gtk.main_quit()

	def exec_game(self, widget, data=None):
		cmd=["dosbox"]
		if ( self.opt_fullscreen != "" ):
			cmd.append(self.opt_fullscreen)
		if ( self.executable.get_text() != "" ):
			cmd.append(self.executable.get_text())
		if ( self.opt_exit != "" ):
			cmd.append(self.opt_exit)
		print("Execute", self.dosboxpath, "with arguments", cmd)
		self.pid=os.spawnv( os.P_NOWAIT, self.dosboxpath, cmd)
	
	def full_toggle(self, widget, data=None):
		self.opt_fullscreen = ("", "-fullscreen")[widget.get_active()]
	
	def dos_toggle(self, widget, data=None):
		self.opt_exit = ("", "-exit")[widget.get_active()]


	def browse_filename(self, widget, data=None):
		self.filesel.show()

	def browse_ok(self, widget, data=None):
		self.executable.set_text(self.filesel.get_filename())
		self.filesel.hide()

	def browse_cancel(self, widget, data=None):
		self.filesel.hide()

	def browse_ignore (self, widget, data=None):
		self.filesel.hide()
		return gtk.TRUE
	
	def add_profile (self, widget, data=None):
		self.add_to_list( self.gname.get_text(), self.executable.get_text(), self.fullscreen.get_active(), self.exitb.get_active())

	def delete_profile (self, widget, data=None):
		iterat = self.selection.get_selected()
		path = self.model.get_path(iterat[1])
		if ( path[0] > 0 ):
			self.model.remove(iterat[1])
			self.gamelist.pop(path[0])
			self.store_profiles()

	def add_to_list ( self, name_s, path_s, full_s, dos_s ):
		if (name_s == ""):
			name_s = "Unnamed"
		self.gamelist.append( (name_s, path_s, full_s, dos_s) )
		iter = self.model.append()
		self.model.set(iter, 0, name_s)
		self.store_profiles()
	
	def profile_select (self, widget, data=None):
		iterat = self.selection.get_selected()
		path = self.model.get_path(iterat[1])
		data = self.gamelist[path[0]]
		self.gname.set_text(data[0])
		self.executable.set_text(data[1])
		self.fullscreen.set_active(data[2])
		self.exitb.set_active(data[3])

	def store_profiles (self):
		filename = self.get_prefs_filename()
		outfile = file(filename,'w')
		outfile.write("self.dosboxpath = \"")
		outfile.write(self.dosboxpath)
		outfile.write("\"\nself.profiles = [")
		lprefix = ""
		for dat in self.gamelist:
			outfile.write(lprefix)
			outfile.write("\n(\"")
			outfile.write(dat[0])
			outfile.write("\", \"")
			outfile.write(dat[1])
			outfile.write("\", ")
			outfile.write(("False", "True")[dat[2]])
			outfile.write(", ")
			outfile.write(("False", "True")[dat[3]])
			outfile.write(")")
			lprefix=", "
		outfile.write("]\n")
		outfile.close()

	def restore_profiles (self):
		filename=self.get_prefs_filename()
		try:
			outfile = file(filename,'r')
			exec(compile(open(filename).read(), filename, 'exec'))
			outfile.close()
			for dat in self.profiles:
				self.add_to_list(dat[0], dat[1], dat[2], dat[3])
		except IOError:
			print("Filename",filename,"not found. Creating with default parameters.")
			self.add_to_list ('Default', '', False, False)
			
	
	def get_prefs_filename (self):
		home = os.environ.get('HOME')
		return home+'/'+'.pydosbox'

prog=Base()

Here is what I get when I run

automake-1.16
automat-visualize3
autopoint
autoreconf
autoscan
autoupdate
avahi-autoipd
avahi-browse
avahi-browse-domains
avahi-daemon
avahi-publish
avahi-publish-address
avahi-publish-service
avahi-resolve
avahi-resolve-address
avahi-resolve-host-name
avahi-set-host-name
awk
axfer
b2sum
badblocks
base32
base64
basename
bash
bashbug
batch
[email protected]:~$ ")
> 
Display all 2687 possibilities? (y or n)
!
./
:
[
[[
]]
{
}
2to3-2.7
7z
7za
7zr
a11y-profile-manager-indicator
aa-enabled
aa-exec
aa-remove-unknown
aa-status
aa-teardown
accessdb
aclocal
aclocal-1.16
aconnect
acpid
acpi_listen
add-apt-repository
addgnupghome
addgroup
addpart
addr2line
add-shell
adduser
agetty
alacarte
alias
alien
alsa
alsabat
alsabat-test
alsactl
alsa-info
alsaloop
alsamixer
alsatplg
alsaucm
ambiguous_words
amidi
amixer
> ame=self.get_prefs_filename()
> 
Display all 2687 possibilities? (y or n)
!
./
:
[
[[
]]
{
}
2to3-2.7
7z
7za
7zr
a11y-profile-manager-indicator
aa-enabled
aa-exec
aa-remove-unknown
aa-status
aa-teardown
accessdb
aclocal
aclocal-1.16
aconnect
acpid
acpi_listen
add-apt-repository
addgnupghome
addgroup
addpart
addr2line
add-shell
adduser
agetty
alacarte
alias
alien
alsa
alsabat
alsabat-test
alsactl
alsa-info
alsaloop
alsamixer
alsatplg
alsaucm
ambiguous_words
amidi
amixer
amuFormat.sh
anacron
animate
animate-im6
animate-im6.q16
any2djvu
apg
apgbfm
aplay
aplaymidi
apparmor_parser
apparmor_status
applygnupgdefaults
apport-bug
apport-cli
apport-collect
apport-unpack
appres
appstreamcli
apropos
apt
apt-add-repository
apt-cache
> ame,'r')
> 
Display all 2687 possibilities? (y or n)
> (filename).read(), filename, 'exec'))
> 
Display all 2687 possibilities? (y or n)
!
./
:
[
[[
]]
{
}
2to3-2.7
7z
7za
7zr
a11y-profile-manager-indicator
aa-enabled
aa-exec
aa-remove-unknown
aa-status
aa-teardown
accessdb
aclocal
aclocal-1.16
aconnect
acpid
acpi_listen
add-apt-repository
addgnupghome
addgroup
addpart
addr2line
add-shell
adduser
agetty
alacarte
alias
alien
alsa
alsabat
alsabat-test
alsactl
alsa-info
alsaloop
alsamixer
alsatplg
alsaucm
ambiguous_words
amidi
>  self.profiles:
> 
Display all 2687 possibilities? (y or n)
!
./
:
[
[[
]]
{
}
2to3-2.7
7z
7za
7zr
a11y-profile-manager-indicator
aa-enabled
aa-exec
aa-remove-unknown
aa-status
aa-teardown
accessdb
aclocal
aclocal-1.16
aconnect
acpid
acpi_listen
add-apt-repository
addgnupghome
addgroup
addpart
addr2line
add-shell
adduser
agetty
alacarte
alias
alien
alsa
alsabat
alsabat-test
alsactl
alsa-info
alsaloop
alsamixer
alsatplg
alsaucm
ambiguous_words
amidi
amixer
amuFormat.sh
anacron
animate
animate-im6
animate-im6.q16
any2djvu
apg
apgbfm
aplay
aplaymidi
apparmor_parser
apparmor_status
applygnupgdefaults
apport-bug
apport-cli
apport-collect
apport-unpack
appres
appstreamcli
apropos
apt
apt-add-repository
apt-cache
apt-cdrom
apt-config
aptd
aptdcon
apt-extracttemplates
apt-ftparchive
apt-get
aptik
aptik-gtk
aptik-gtk-launcher
aptitude
aptitude-create-state-bundle
aptitude-curses
aptitude-run-state-bundle
apt-key
apt-mark
apt-sortpkgs
apturl
apturl-gtk
ar
arch
arecord
arecordmidi
arm2hpdl
> t("Filename",filename,"not found. Creating with default parameters.")
> 
.adobe/
Aptik/
.aqbanking/
.bash_history
Being light - Christian Science.mp3
.cache/
Calibre Library/
.config/
Create A List Of Installed Packages And Install Them Later From The List.odt
.dbus/
Desktop/
.dmrc
Documents/
DOS/
.dosbox/
Downloads/
.dropbox/
Dropbox/
.dropbox-dist/
dwhelper/
FarmPower.odt
.gconf/
GnuCash/
.gnupg/
gtk,gobject,os
.icons/
Imprimis_May_June_2018_Pence_Our_Greatest_Inheritance.pdf
KindleGen/
ListInstall.png
list.txt
.local/
.macromedia/
Manjaro Cache/
.mozilla/
Music/
My Kindle Content/
My Safes/
.nv/
Pictures/
pkglist.txt
.pki/
.PlayOnLinux/
PlayOnLinux's virtual drives/
Public/
.pydosbox
snap/
.ssh/
Stacer_1.0.4_amd64.deb
.stellarium/
.sudo_as_admin_successful
Templates/
.themes/
.thunderbird/
.unison/
unison.log
Videos/
VirtualBox VMs/
.wget-hsts
.wine/
Workout01.xspf
Workout1.pls
Workout2.pls
.Xauthority
.xsession-errors
.xsession-errors.old
> '', False, False)
> 
.adobe/
Aptik/
.aqbanking/
.bash_history
Being light - Christian Science.mp3
.cache/
Calibre Library/
.config/
Create A List Of Installed Packages And Install Them Later From The List.odt
.dbus/
Desktop/
.dmrc
Documents/
DOS/
.dosbox/
Downloads/
.dropbox/
Dropbox/
.dropbox-dist/
dwhelper/
FarmPower.odt
.gconf/
GnuCash/
.gnupg/
gtk,gobject,os
.icons/
Imprimis_May_June_2018_Pence_Our_Greatest_Inheritance.pdf
KindleGen/
ListInstall.png
list.txt
.local/
.macromedia/
Manjaro Cache/
.mozilla/
Music/
My Kindle Content/
My Safes/
.nv/
Pictures/
pkglist.txt
.pki/
.PlayOnLinux/
PlayOnLinux's virtual drives/
Public/
.pydosbox
snap/
.ssh/
Stacer_1.0.4_amd64.deb
> ame (self):
> 
.adobe/
Aptik/
.aqbanking/
.bash_history
Being light - Christian Science.mp3
.cache/
Calibre Library/
.config/
Create A List Of Installed Packages And Install Them Later From The List.odt
.dbus/
Desktop/
.dmrc
Documents/
DOS/
.dosbox/
Downloads/
.dropbox/
Dropbox/
.dropbox-dist/
dwhelper/
FarmPower.odt
.gconf/
GnuCash/
.gnupg/
gtk,gobject,os
.icons/
Imprimis_May_June_2018_Pence_Our_Greatest_Inheritance.pdf
KindleGen/
ListInstall.png
list.txt
.local/
.macromedia/
Manjaro Cache/
.mozilla/
Music/
My Kindle Content/
My Safes/
.nv/
Pictures/
pkglist.txt
.pki/
.PlayOnLinux/
PlayOnLinux's virtual drives/
Public/
.pydosbox
snap/
.ssh/
Stacer_1.0.4_amd64.deb
.stellarium/
.sudo_as_admin_successful
Templates/
.themes/
.thunderbird/
.unison/
unison.log
Videos/
VirtualBox VMs/
.wget-hsts
.wine/
Workout01.xspf
Workout1.pls
Workout2.pls
.Xauthority
.xsession-errors
.xsession-errors.old
> os.environ.get('HOME')
> 
.adobe/
Aptik/
.aqbanking/
.bash_history
Being light - Christian Science.mp3
.cache/
Calibre Library/
.config/
Create A List Of Installed Packages And Install Them Later From The List.odt
.dbus/
Desktop/
.dmrc
Documents/
DOS/
.dosbox/
Downloads/
.dropbox/
Dropbox/
.dropbox-dist/
dwhelper/
FarmPower.odt
.gconf/
GnuCash/
>  home+'/'+'.pydosbox'
> 
> prog=Base()^C
[email protected]pc:~$

What do you get it you type the following into the terminal?

python2 -c 'import gtk'

then try:

python2 -c 'import gobject'

If these are not installed for python2, you will get a message back like the following after you hit enter:

Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named gtk

If that is the case, I can provide some advice for where to install the missing parts.

1 Like

Yes. That is the error message I got for both commands.

When the script file was written it required python 2.3 and pygtk 2.0. It also required gobject. MATE 19.10 automatically installed a symlink python-is-python2. This symlink is not automatically installed under MATE 20.04, but installing it did not help. I cannot find pygtk in the repositories. I found gobject as python-gobject, but am not sure which version to install. I'm thinking that my script file has some unmet dependencies, but am not sure how to determine that. Any suggestions?

The first executable line in my script is import gtk,gobject,os. I'm guessing that these are the dependencies that need to be satisfied.

Well, I tried to pull together instructions on how to install the Python2 GObject and PyGtk on 20.04 but it also occurred to me that maybe it was time for this script to just be updated. Check it out on Github.

When I run it, the GUI launches but I have not tested everything else. Please let me know how it works for you either here or on Github.

I tried changing your commands somewhat. Running python3 -c 'from gi.repository import Gtk' I get

PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.

Running python3 -c 'from gi.repository import PyGObject' I get

Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3/dist-packages/gi/importer.py", line 132, in load_module
        raise ImportError('cannot import name %s, '
    ImportError: cannot import name PyGObject, introspection typelib not found

And runnng python3 -c 'from gi.repository import os' I get

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/gi/importer.py", line 132, in load_module
    raise ImportError('cannot import name %s, '
ImportError: cannot import name os, introspection typelib not found

If you can help me with the syntax on these commands I think I can get my python script running.

Those commands were just to check if the issue you were having was related to missing dependencies or something else. They aren't a fix to the program per se.

Since you are getting those errors with

python3 -c 'import gi' etc

I am pretty sure that you have python3 gi (apt package python3-gi) installed. This should be enough to run the Python3 version of the script.

I think we were posting to each other at the same time with the last post. I downloaded the updated file from Github, but am unable to get it to launch.

I've just completed a fresh install of 20.04, and I understand it includes python3 and GTK 3. However, I am unable to confirm that I have GTK 3 on my machine. What version (or the exact filename) of GTK should I look for?

How are you trying to launch it?

You can check if you have the correct Python3 packages by entering the following at the terminal:

python3 -c 'import gi; gi.require_version("Gtk","3.0"); import os; from gi.repository import Gtk'

If you have the dependencies installed, there will be no text returned. If you don't have them installed, you will see errors like before.

I ran the command in terminal and got no error messages.

I launch the script with a launcher on my desktop. The file permissions for the launcher and the script are in my name. Should anything be in root?

Script still does not run.