web-dev-qa-db-fra.com

Exécuter la commande de terminal à partir de python dans la nouvelle fenêtre de terminal?

L'objectif ici est d'exécuter un nouveau fichier python dans un nouveau shell à partir d'un fichier python existant dans un shell existant. Disons que j'ai deux fichiers, aaa.py et bbb.py. Disons pour la simplicité que tout ce que aaa.py fait est ...

subprocess.call('python bbb.py', Shell=True)

... et disons que bbb.py fait est ...

print 'It worked'

L'objectif est maintenant de lancer aaa.py dans le terminal 1 et de le lancer pour lancer bbb.py dans le terminal 2. Je m'attendrais à ce que la commande ci-dessous existe, mais je ne peux pas le comprendre. 

subprocess.call_in_new_window('python bb.py', Shell=True)
15
Evan Cathcart

Il n'y a aucun moyen de faire cela en général à partir d'un Shell. Ce que vous devez faire est d’exécuter le programme de terminal lui-même ou un programme de lancement qui le fait pour vous. Et la manière de le faire est différente pour chaque programme de terminal.

Dans certains cas, os.startfile fera ce que vous voulez, mais cela ne sera pas universel.

En outre, notez qu'en général, vous allez avoir besoin d'un chemin absolu vers votre script, car la nouvelle fenêtre de terminal exécutera un nouveau shell et n'aura donc pas nécessairement le même répertoire de travail. Mais je vais ignorer cela pour les exemples.


Avec Windows cmd, la méthode la plus simple consiste à utiliser la commande start Shell. Si vous start correspond à un programme en ligne de commande, y compris python, une nouvelle fenêtre cmd s'affichera. Donc, quelque chose comme:

subprocess.call('start /wait python bb.py', Shell=True)

OS X a une commande similaire, open . Et c'est un vrai programme plutôt qu'une commande Shell, vous n'avez donc pas besoin de Shell=True. Toutefois, l'exécution d'un programme ou d'un script en ligne de commande avec open n'ouvre généralement pas de nouvelle fenêtre de terminal. En fait, l'objectif est de vous permettre d'exécuter des programmes comme s'ils étaient double-cliqués dans le Finder, ce qui n'exécutera jamais quelque chose dans le terminal, à moins que ce ne soit un fichier .command.

Vous pouvez donc créer un fichier wrapper .command temporaire et open that; quelque chose comme ceci (non testé):

with tempfile.NamedTemporaryFile(suffix='.command') as f:
    f.write('#!/bin/sh\npython bb.py\n')
    subprocess.call(['open', '-W', f.name])

Sinon, vous pouvez explicitement indiquer à open d'utiliser Terminal.app, par exemple:

subprocess.call(['open', '-W', '-a', 'Terminal.app', 'python', '--args', 'bb.py'])

Ou vous pouvez écrire un script Terminal.app via AppleEvents. Par exemple:

appscript.app('Terminal').do_script('python bb.py')

L'événement "do script" ouvre une nouvelle fenêtre et exécute son argument sous forme de commande. Si vous souhaitez un contrôle plus détaillé, ouvrez le dictionnaire de script dans l'éditeur AppleScript et découvrez tout ce que vous pouvez faire en termes d'amusement.


Sur Linux ou d’autres systèmes * nix, il existe 65 102 environnements de bureau, lanceurs et programmes de terminal différents. Avez-vous besoin de travailler sur chacun d'eux?

Avec gnome-terminal, une nouvelle exécution du terminal vous donne une nouvelle fenêtre et l'argument -x vous permet de spécifier une commande initiale, ainsi:

subprocess.call(['gnome-terminal', '-x', 'python bb.py'])

De nombreux terminaux plus anciens essaient d'être compatibles avec xterm, qui fait la même chose avec -e, donc:

subprocess.call(['xterm', '-e', 'python bb.py'])
subprocess.call(['rxvt', '-e', 'python bb.py'])

… etc.

Comment savez-vous quel terminal l'utilisateur utilise? Bonne question. Vous pouvez suivre le même chemin que les processus parents jusqu'à ce que vous trouviez quelque chose qui ressemble à un terminal. Ou vous pouvez simplement supposer que tout le monde a xterm. Vous pouvez aussi regarder comment différentes distributions configurent un terminal par défaut et les recherchent toutes. Ou…

25
abarnert

Vous ne pourrez pas y arriver, du moins pas aussi simplement que vous le pensez. Je suppose que vous parlez d'un Mac à cause de la "fenêtre de terminal".

Vous pourrez peut-être y arriver en utilisant le système X Window, mais vous aurez besoin d'un tas de choses à configurer, de serveurs X, d'autorisations, etc. pour y arriver.

De nos jours, de telles choses violent généralement les limites de sécurité normales. Supposons que vous téléchargiez un programme qui se comporte comme vous le suggérez. Il ouvre une fenêtre (terminal) (invisible pour vous) qui a les mêmes privilèges que vous avez. Il procède à la lecture de tous vos répertoires et fichiers et les envoie à l'auteur du programme. Vous pourriez ne pas être heureux avec ça. Pendant tout ce temps, vous pensez jouer à un jeu, puis vous arrêtez et le second Shell continue à fonctionner.

Les fenêtres et les coques sont un peu disjointes. 

2
Fred Mitchell

Cela devrait probablement être un commentaire, mais comme je ne peux pas encore ...

Sous Windows, vous pouvez faire:

subprocess.call('python bb.py', creationflags=subprocess.CREATE_NEW_CONSOLE)
1
DSM