Hallo an alle. Ich bin relativ neu in Python und bräuchte mal ein wenig Rat und Hilfe. Ich bin zwar kein vollständiger Anfänger im Bereich der Programmierung, aber auch kein C/C++ Experte. ... so mal nur als Vorwarnung.^^ Es ist im Grunde kein spezielles Problem, bin mir halt nur nicht ganz sicher.
Wie sollte ich mein Programm arrangieren und ist der Code so ok? Ziel ist es hierbei das Programm modularisch aufzubauen.
Es soll ein gar nicht so komplizierter CLI & GUI Launcher für ein bestimmtes Programm werden. Es geht um den Emulator M.A.M.E.. Es wird einen temporären Verzeichnis generieren und Gui zum eingeben des Highscore erzeugen etc... Wie wäre es zum Beispiel mit solch einer Struktur: (mamehi ist der Name des Projektes)
- Mamehi/
- mamehi/
- commandline.py (unabhängige Klasse zum Aufrufen von Programmen, wrapper für subprocess.Popen)
- filesystem.py (Sammlung von Funktionen die mit Dateisystem zu tun haben und in keine andere Kategorie passen)
- __main__.py (erzeugt Haupt-Mamehi Instanz und ruft main() auf, anschließend sys.exit())
- mamehi.py (einzelne Klasse mit main Methode und optionen parsen etc)
- splitpath.py (einzelne Klasse zum Teilen eines strings in seine Pfad-Bestandteile und zum absolut machen)
- make.sh
- setup.py
- README
- mamehi/
Hier ich poste mal die commandline.py Klasse. Was haltet ihr von den Kommentaren und den Stil? Ist allerdings in Englisch:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
"""
Copyright (c) 2011, Tuncay
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
"""
import os
import subprocess
import shlex
import copy
class CommandLine:
"""
Prepares and runs a command line and gets it output. Command can be a
list of arguments or a single string with all arguments. In that case,
it will be converted back to a list, by analizing its parts.
Attributes: (read-only)
command -- The actual command line as a list.
Methodes:
add_arg -- Adds arguments to the command.
remove_arg -- Removes argument from command.
execute -- Runs the command and gets it output.
Examples:
>>> cmd = CommandLine('echo')
>>> print cmd.add_arg('hello world')
['echo', 'hello world']
>>> print cmd.execute('!'),
hello world !
"""
def __init__(self, command):
"""
Initiates the command from list or string.
Parameters:
command -- An args list to execute with Popen. If this is a
string, then it will be analyzed and splitted up into a list of
args with shlex.split() function.
Remarks:
Saves the command line as an instance attribute to be used later.
Accepts lists and single strings only.
"""
if isinstance(command, list):
self.command = command
elif isinstance(command, basestring):
self.command = shlex.split(command)
else:
raise TypeError()
def add_arg(self, value):
"""
Appends additional arguments to the current command.
Parameters:
value -- Can be a list, which then extends the command args list.
If this is a string, then string will be appended as a single
entry in commands args list.
Return:
The updated command.
Remarks:
Changes the self.command attribute directly.
"""
if isinstance(value, basestring):
self.command.append(value)
elif isinstance(value, list):
self.command.extend(value)
else:
raise TypeError()
return self.command
def remove_arg(self, value):
"""
Remove an single argument by matching value.
Parameters:
value -- A string entry to remove from commands list of args
entries. If this is a list, then all matching strings are
removed.
Return:
The updated command.
Remarks:
Changes the self.command attribute directly.
"""
if isinstance(value, basestring):
if value in self.command:
self.command.remove(value)
elif isinstance(value, list):
for a in value:
if a in self.command:
self.command.remove(a)
else:
raise TypeError()
return self.command
def execute(self, args=None, wait=True, workingdir=None):
"""
Executes the command and get its output.
Parameters:
args -- Additional arguments (list or string) to use at execute
time only.
wait -- If set to True, then stdout and stderr are catched and
returned. If set to False, then script does not wait until
programs execution is ended and gets the pid as return value.
workingdir -- Uses the this folder as working dir and changes
temporary the current working dir of script.
Return:
Catches the stdout and stderr output of console (without showing
console) and gets them together as a single string.
"""
# Backup the current working dir, for temporary change.
if workingdir is not None:
cwd_backup = os.getcwd()
os.chdir(workingdir)
# Make a copy of the command, for making temporary changes on it.
command = copy.copy(self.command)
# Temporary add additional arguments to the command, if specified.
if args is not None:
if isinstance(args, basestring):
command.append(args)
elif isinstance(args, list):
command.extend(args)
else:
raise TypeError()
# Execute the command. Do not use the shell, as the command is
# expected to be a list. The stdout and stderr are piped together into
# a single string.
proc = subprocess.Popen(command,
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
cwd=workingdir)
# Revert to saved previous current working dir.
if workingdir is not None:
os.chdir(cwd_backup)
# Get the stdout and stderr output from console or the process pid.
if wait:
retval = proc.communicate()[0]
else:
retval = proc.pid
return retval
if __name__ == "__main__":
import doctest
doctest.testmod()