[Risolto] Python, MS Finestre, GTK e lancio applicazioni

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
Ph1l
Linux 2.x
Linux 2.x
Messaggi: 232
Iscritto il: gio 4 gen 2007, 13:55
Slackware: 12.0
Località: Acerra (NA)
Contatta:

[Risolto] Python, MS Finestre, GTK e lancio applicazioni

Messaggio da Ph1l »

Salve.
Sto giocando da un pochino con questo linguaggio dalle infinite qualità, per ora puntando a risolvere i problemi più facili e da newbie.

Un amico mi ha chiesto un piccolo programmino per Finestre leggero, che permetta di modificare un file di configurazione (composto da solo testo) e avviare l'exe principale.

Ho deciso di scrivere l'interfaccia in GTK (che ogni Finestre che si rispetti ha installato) e il codice in python.

Per la grafica ci sto lavorando (ah, se qualcuno ha un tutorial facile facile passi pure ;) ), la modifica del file è assai banale, ma il grattacapo mi viene quando si tratta di eseguire il file exe.

Cercando in giro ho trovato due possibilità:

Codice: Seleziona tutto

win32api.WinExec("programma.exe")
oppure:

Codice: Seleziona tutto

os.system("programma.exe")
Tutti e due, però, danno lo stesso problema: vengono eseguiti come dipendenti (non sarà il termine più adatto, ma non ne conosco altri e almeno questo rende l'idea :lol: ) dalla funzione principale.

Ad esempio, se il programma prova ad accedere alle rete il firewall segna il tentativo come effettuato da "python.exe". Inoltre lo stesso programma va più lento (a detta dell'amico) rispetto a quando viene lanciato direttamente.

Idee?
Grazie ^_*
Ultima modifica di Ph1l il mer 21 nov 2007, 17:52, modificato 1 volta in totale.

Avatar utente
aschenaz
Staff
Staff
Messaggi: 4623
Iscritto il: mer 28 lug 2004, 0:00
Nome Cognome: Nino
Slackware: current
Kernel: 5.4.x
Desktop: KDE
Località: Reggio Calabria
Contatta:

Messaggio da aschenaz »

Anni fa ho usato questo:
http://www.py2exe.org/

Vedi se può fare al caso tuo.

Ma probabilmente, ho capito tutta un'altra cosa... :oops:

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Codice: Seleziona tutto

#!/usr/bin/python                                                               

# ...                                                                           

# esegue cmd in un processo separato                                            
def execute(cmd, args =[""]) :
    import os

    if os.fork() :
        os.execvpe(cmd, args, os.environ)


# ...                                                                           

execute("programma.exe")

# ...  
Il problema è: su windows puoi usare fork() ?

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Per le GTK: http://www.pygtk.org/pygtk2tutorial/index.html

Ma se hai già qualche esperienza con le GTK ti basta la guida di riferimento: http://www.pygtk.org/pygtk2reference/ alla fine le api sono (quasi) sempre le stesse.

Avatar utente
Ph1l
Linux 2.x
Linux 2.x
Messaggi: 232
Iscritto il: gio 4 gen 2007, 13:55
Slackware: 12.0
Località: Acerra (NA)
Contatta:

Messaggio da Ph1l »

Grazie mille per le risposte, anche per il py2exe che mi tornerà utile dopo :D

Per il fork()...
File "<pyshell#6>", line 3, in execute
if os.fork() :
AttributeError: 'module' object has no attribute 'fork'
Lo prendo come un "non puoi usarlo"?

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Come temevo.. Puoi provare qualcosa come:
os.system("start programma.exe")

Non ho idea se si possa usare "start" in quel modo però...

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio da absinthe »

prova questo!

Codice: Seleziona tutto

#prova di gestione subprocessi

#importo gli oggetti necessari
from subprocess import *

#invoco un processo e attendo la sua fine. memorizzo l'output in una PIPE
myExternalExecutable = Popen("C:\WINDOWS\system32\cmd.exe /C dir",0, \
                             "C:\WINDOWS\system32\cmd.exe",None,PIPE);

#comunico con il tizio... e aspetto che abbia finito
(outdata,errdata) = myExternalExecutable.communicate();
print(outdata)
è una prova che ho fatto perchè volevo vedere se c'era qualcosa per far comunicare i processi! primo e unico programmino da me fatto in python e poi abbandonato per carenza di tempo. il modulo subprocess viene usato per il lancio di vari thread se ricordo bene... http://docs.python.org/lib/module-subprocess.html

M

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Ma il processo in quel caso non è sempre figlio dello script? Risolve il problema del firewall? (Non è una domanda retorica, non ho mai programmato su Windows).

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Ad ogni modo, quella chiamata è bloccante. Deve far partire un thread o forkare il processo, altrimenti all'invocazione del programma gli si blocca la gui.

Questo ovviamente vale anche per il mio os.system(start applicazione) che, a parte che non so se lanci davvero il programma, deve far parte di un thread separato.

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio da absinthe »

per quanto riguarda la chiamata: quella è sì bloccante ma esistono nello stesso modulo chiamate non bloccanti per processamenti in parallelo. mi sono documentato un pò aprendo le api c di windows.

l'msdn in riferimento alle api di windows dice che (sperando di non infrangere copyright vari):
_spawnl, _wspawnl
Create and execute a new process.


int _spawnl( int mode, const char *cmdname, const char *arg0, const char *arg1, ... const char *argn, NULL );

int _wspawnl( int mode, const wchar_t *cmdname, const wchar_t *arg0, const wchar_t *arg1, ... const wchar_t *argn, NULL );

Routine Required Header Compatibility
_spawnl <process.h> Win 95, Win NT
_wspawnl <stdio.h> or <wchar.h> Win NT


For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBC.LIB Single thread static library, retail version
LIBCMT.LIB Multithread static library, retail version
MSVCRT.LIB Import library for MSVCRT.DLL, retail version


Return Value

The return value from a synchronous _spawnl or _wspawnl (_P_WAIT specified for mode) is the exit status of the new process. The return value from an asynchronous _spawnl or _wspawnl (_P_NOWAIT or _P_NOWAITO specified for mode) is the process handle. The exit status is 0 if the process terminated normally. You can set the exit status to a nonzero value if the spawned process specifically calls the exit routine with a nonzero argument. If the new process did not explicitly set a positive exit status, a positive exit status indicates an abnormal exit with an abort or an interrupt. A return value of –1 indicates an error (the new process is not started). In this case, errno is set to one of the following values:

E2BIG

Argument list exceeds 1024 bytes

EINVAL

mode argument is invalid

ENOENT

File or path is not found

ENOEXEC

Specified file is not executable or has invalid executable-file format

ENOMEM

Not enough memory is available to execute new process

Parameters

mode

Execution mode for calling process

cmdname

Path of file to be executed

arg0, ... argn

List of pointers to arguments

Remarks

Each of these functions creates and executes a new process, passing each command-line argument as a separate parameter.

Process and Environment Control Routines | _spawn Functions Overview

See Also abort, atexit, _exec Functions, exit, _flushall, _getmbcp, _onexit, _setmbcp, system

Example

/* SPAWN.C: This program accepts a number in the range
* 1-8 from the command line. Based on the number it receives,
* it executes one of the eight different procedures that
* spawn the process named child. For some of these procedures,
* the CHILD.EXE file must be in the same directory; for
* others, it only has to be in the same path.
*/

#include <stdio.h>
#include <process.h>

char *my_env[] =
{
"THIS=environment will be",
"PASSED=to child.exe by the",
"_SPAWNLE=and",
"_SPAWNLPE=and",
"_SPAWNVE=and",
"_SPAWNVPE=functions",
NULL
};

void main( int argc, char *argv[] )
{
char *args[4];

/* Set up parameters to be sent: */
args[0] = "child";
args[1] = "spawn??";
args[2] = "two";
args[3] = NULL;

if (argc <= 2)
{
printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );
exit( 1 );
}

switch (argv[1][0]) /* Based on first letter of argument */
{
case '1':
_spawnl( _P_WAIT, argv[2], argv[2], "_spawnl", "two", NULL );
break;
case '2':
_spawnle( _P_WAIT, argv[2], argv[2], "_spawnle", "two",
NULL, my_env );
break;
case '3':
_spawnlp( _P_WAIT, argv[2], argv[2], "_spawnlp", "two", NULL );
break;
case '4':
_spawnlpe( _P_WAIT, argv[2], argv[2], "_spawnlpe", "two",
NULL, my_env );
break;
case '5':
_spawnv( _P_OVERLAY, argv[2], args );
break;
case '6':
_spawnve( _P_OVERLAY, argv[2], args, my_env );
break;
case '7':
_spawnvp( _P_OVERLAY, argv[2], args );
break;
case '8':
_spawnvpe( _P_OVERLAY, argv[2], args, my_env );
break;
default:
printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );
exit( 1 );
}
printf( "from SPAWN!\n" );
}


Output

SYNTAX: SPAWN <1-8> <childprogram>
in riferimento a spawn e simili la documentazione python dice che sono state rimpiazzate da Popen: http://docs.python.org/lib/node538.html in particolare pare che per lanciare un nuovo processo in maniera asincrona occorra usare:

Codice: Seleziona tutto

pid = Popen(["/bin/mycmd", "myarg"]).pid
quindi se non fanno casino tra iò che è thread e ciò che è processo Popen (in una della sue varianti) dovrebbe essere ok!

M

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

Ho provato, sembra ok!

Codice: Seleziona tutto

Popen("programma.exe", 0)
Dovrebbe fare esattamente ciò che è richiesto da Ph1l

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio da absinthe »

cavoli! anticipato! ho chiuso ora il visual c++ e volevo proprio fare il test! :o
M

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Messaggio da gallows »

ghgh

Funziona anche con:

Codice: Seleziona tutto

import os
# ...
os.spawnvpe(os.P_NOWAIT, "programma.exe", [""], os.environ) 

Avatar utente
Ph1l
Linux 2.x
Linux 2.x
Messaggi: 232
Iscritto il: gio 4 gen 2007, 13:55
Slackware: 12.0
Località: Acerra (NA)
Contatta:

Messaggio da Ph1l »

Provato con tutti e due...

Codice: Seleziona tutto

>>> popen("notepad.exe", 0)
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    popen("notepad.exe", 0)
NameError: name 'popen' is not defined
>>> os.spawnvpe(os.P_NOWAIT, "programma.exe", [""], os.environ)
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    os.spawnvpe(os.P_NOWAIT, "programma.exe", [""], os.environ)
AttributeError: 'module' object has no attribute 'spawnvpe'
naturalmente ho dato prima un import os...

Per spawnvpe credo non esista per Win, a quanto leggo

qui:
Disponibilità: Unix, Windows. spawnlp(), spawnlpe(), spawnvp() and spawnvpe() non sono disponibili in Windows.
per popen non ho trovato nulla.

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio da absinthe »

per popen:
absinthe ha scritto: #importo gli oggetti necessari
from subprocess import *
l'ho usato su win quindi non dovrebbero esserci problemi.

M

Rispondi