Pagina 1 di 2

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

Inviato: mar 20 nov 2007, 21:08
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 ^_*

Inviato: mar 20 nov 2007, 21:23
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:

Inviato: mar 20 nov 2007, 22:05
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() ?

Inviato: mar 20 nov 2007, 22:12
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.

Inviato: mar 20 nov 2007, 23:36
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"?

Inviato: mar 20 nov 2007, 23:53
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ò...

Inviato: mer 21 nov 2007, 10:35
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

Inviato: mer 21 nov 2007, 12:16
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).

Inviato: mer 21 nov 2007, 12:36
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.

Inviato: mer 21 nov 2007, 13:18
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

Inviato: mer 21 nov 2007, 13:36
da gallows
Ho provato, sembra ok!

Codice: Seleziona tutto

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

Inviato: mer 21 nov 2007, 13:39
da absinthe
cavoli! anticipato! ho chiuso ora il visual c++ e volevo proprio fare il test! :o
M

Inviato: mer 21 nov 2007, 13:45
da gallows
ghgh

Funziona anche con:

Codice: Seleziona tutto

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

Inviato: mer 21 nov 2007, 16:10
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.

Inviato: mer 21 nov 2007, 17:15
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