質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • Python 3.x

    4848questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Pythonで別プログラムを起動させたい

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 146

hyugasatsuman5

score 10

 Pythonで別のプログラムを起動させたい

Pythonで3つのプログラムを作り、一方を起動させるともう一方の方も並行して起動させるプログラムを作ろうと思っているんですがなかなかうまく行きません、どうしたらいいでしょうか?

 試したこと

例えばmainA.pyとsubB.py、subC.pyを作ります

mainA.pyには

import subprocess as sb
import time

#3回繰り返します
for count in range(3):

    #Hello!を出力
    print("Hello!")
    #suB.pyを起動
    sb.check_call({"python","subB.py"})
    #Aを出力
    print("A")

    #3秒停止
    time.sleep(3)

    #subC.pyを起動
    sb.check_call(["python","subC.py"])
    #Dを出力
    print("D")

subB.py

import time

#Call me?を出力
print("Call me?")

#5秒停止
time.sleep(5)

#Bを出力
print("B")

subC.py

import time

#What happened?を出力
print("What happened?")

#5秒停止
time.sleep(5)

#Cを出力
print("C")

という感じでmainA.pyを起動するとsubB.py、subC.pyが並行して起動する形にします

ここまではできたんですがただこの形にすると
出力結果は

Hello!
Call me?
B
A
What happened?
C
D
Hello!
Call me?
B
A
What happened?
C
D
Hello!
Call me?
B
A
What happened?
C
D

上記のようになりますが”A”と”D”の文字が出力するまでBとCのプログラムのおかげでそれぞれ5秒かかってしまいます
また”D”の文字が出力したあとすぐにHello!を出力されますがただ2巡目のHello!を出力するまで13秒かかります
Aプログラムの3秒はいいのですがやはりBとCのプログラムのおかげで10秒が余計にかかってしまいます

ただ私としてはBとCのプログラムを起動はするんですが”A”と”D”は優先的に出力、というよりもAのプログラムは先に処理済まさせたいと思っています
結果的にはBとCのプログラムはAのプログラムに干渉せず独立した形で起動させたいです

ただ単純に起動させるだけでいいのですがどうしたらいいでしょうか

osを使っても

import os
import time

#3回繰り返します
for count in range(3):

    #Hello!を出力
    print("Hello!")
    #suB.pyを起動
    os.system({"C:\Users\亮\PycharmProjects\untitled1\venv\subB.py"})
    #Aを出力
    print("A")

    #3秒停止
    time.sleep(3)

    #subC.pyを起動
    os.system(["C:\Users\亮\PycharmProjects\untitled1\venv\subC.py"])
    #Dを出力
    print("D")
  File "C:/Users/亮/PycharmProjects/untitled1/venv/btmainA.py", line 10
    os.system({"C:\Users\亮\PycharmProjects\untitled1\venv\btsubB.py"})
              ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

Process finished with exit code 1


という感じでエラーが出てしまいます

 補足情報(FW/ツールのバージョンなど)

Windows8.1
Python3.6.3
PyCharm

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+4

Popenオブジェクトを使うと良いかと思います。
ただし、先に親プロセスが閉じないように留意する必要があります。

mainA.py

import subprocess as sb
import time

print('start', time.time())

#
print("call subB", time.time())
pb = sb.Popen(["python", "subB.py"])
print("called subB", time.time())

#
time.sleep(3)

#
print("call subC", time.time())
pc = sb.Popen(["python","subC.py"])
print("called subC", time.time())

#
# 終了待ち
pb.wait()
pc.wait()

print('finish', time.time())

subB.py

import time

print("SubB start", time.time())
time.sleep(5)
print("SubB end", time.time())

subC.py

import time

print("subC start", time.time())
time.sleep(5)
print("subC end", time.time())

実行結果 手元のWindows10 + Python3.6.0

start       1526709671.3939173
call subB   1526709671.394894
called subB 1526709671.3978899
SubB start  1526709671.450421
call subC   1526709674.3979313
called subC 1526709674.3999634
subC start  1526709674.449803
SubB end    1526709676.4504917
subC end    1526709679.449869
finish      1526709679.4569793

註:少し見やすく成形しています。

参考:python でコマンド実行。サブプロセスの終了待ち・強制終了・親プロセスと一緒に殺す。

ついでに

SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

パスを区切っているバックスラッシュによって、エスケープシーケンスが働いているせいです。
文字列リテラルの先頭にrプレフィックスを付けるのが楽な解決法です。

r"C:\Users\name\PycharmProjects\untitled1\venv\btsubB.py"

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+3

subBsubCsubprocess.Popenで非同期で起動すればよいと思います。
sb.check_call({"python","subB.py"})sb.Popen(["python","subB.py"])

という感じでエラーが出てしまいます

パス文字列に\文字が含まれていますので
os.system({"C:\Users~"})os.system({r"C:\Users~"})のようにr"~"でパスを渡してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/19 15:55

    回答有り難うございます!

    Popenを使えばよかったんですね
    大変助かりました

    キャンセル

  • 2018/05/19 15:57

    他の方も大変わかりやすい解説とあとosのエラーについても親切に教えていただいて有難うございます

    キャンセル

+3

subprocess.Popenを使うと希望の動作になると思います。

import subprocess as sb
import time

#3回繰り返します
cmd1 = "python subB.py".split()
cmd2 = "python subC.py".split()
plst = []
for count in range(3):

    #Hello!を出力
    print("Hello!")
    #suB.pyを起動

    plst.append(sb.Popen(cmd1))
    #Aを出力
    print("A")

    #3秒停止
    # 分かりづらいのでコメントアウト
    # time.sleep(3)

    #subC.pyを起動
    plst.append(sb.Popen(cmd2))
    #Dを出力
    print("D")

for p in plst:
    p.wait()  # 子プロセスの終了待ち

""" =>
Hello!
A
D
Hello!
A
D
Hello!
A
D
Call me?
Call me?
What happened?
What happened?
What happened?
Call me?
B
C
C
B
C
B
"""

参考:
python でコマンド実行。サブプロセスの終了待ち・強制終了・親プロセスと一緒に殺す。 - それマグで!

 追記

どうせpythonプログラムを呼ぶなら、スレッドという手もあります。引数や返り値を扱いたければメリットがあるかもしれません。

main.py

import time
from threading import Thread
import subb
import subc

thlst = []
for count in range(3):
    print("Hello!")
    th = Thread(target=subb.main)
    th.start()
    thlst.append(th)

    print("A")

    time.sleep(3)

    th = Thread(target=subc.main)
    th.start()
    thlst.append(th)

    print("D")

for th in thlst:
    th.join()

subb.py

import time

def main():
    #Call me?を出力
    print("Call me?")

    #5秒停止
    time.sleep(5)

    #Bを出力
    print("B")

if __name__ == "__main__":
    main()

subc.py

import time

def main():
    #What happened?を出力
    print("What happened?")

    #5秒停止
    time.sleep(5)

    #Cを出力
    print("C")

if __name__ == "__main__":
    main()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

subprocessのcheck_callは起動したプログラムが終了するまで待ちますから、mainA.pyのプログラムは
・Hello!と表示
・subB.pyを実行して終わるまで待つ(その間にsubB.pyがCall me?と表示、5秒待ってBと表示して終わる)
・Aと表示
・3秒待つ
・subC.pyを実行して終わるまで待つ(その間にsubC.pyがWhat happened?と表示、5秒待ってCと表示して終わる)
・Dと表示
というように(直列に)実行されます。(残念ながら並列には実行されません。なぜならcheck_callで起動したプログラム(subB.pyやsubC.py)が終わるのを待っているので)

Pythonで並列実行するには、threadを使うのが簡単です。
subB.pyに相当する関数(subB)と、subC.pyに相当する関数(subC)をmainA.pyで定義して、それらをthreadで並列に実行すれば、望んでいるように動作すると思います。

import time
import threading #threadを使うので必要


def subB(): 
    #Call me?を出力
    print("Call me?")
    #5秒停止
    time.sleep(5)
    #Bを出力
    print("B")


def subC():
    #What happened?を出力
    print("What happened?")
    #5秒停止
    time.sleep(5)
    #Cを出力
    print("C")


if __name__ == "__main__":

    for count in range(3):

    #Hello!を出力
    print("Hello!")
    #subBをthreadで実行
    ## threadを用意
    thread_1 = threading.Thread(target=subB)
    ## threadを実行
    thread_1.start()
    #Aを出力
    print("A")

    #3秒停止
    time.sleep(3)

    #subCをthreadで実行
    ## threadを用意
    thread_2 = threading.Thread(target=sunC) 
    ## threadを実行
    thread_2.start()
    #Dを出力
    print("D")

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/20 00:20

    回答ありがとうございます

    下記の方を実行してみたんですが、、、

    ```python
    import time
    import threading #threadを使うので必要


    def subB():
    #Call me?を出力
    print("Call me?")
    #5秒停止
    time.sleep(5)
    #Bを出力
    print("B")


    def subC():
    #What happened?を出力
    print("What happened?")
    #5秒停止
    time.sleep(5)
    #Cを出力
    print("C")


    if __name__ == "__main__":

    for count in range(3):

    # Hello!を出力
    print("Hello!")
    #subBをthreadで実行
    ## threadを用意
    thread_1 = threading.Thread(target=subB)
    ## threadを実行
    thread_1.start()
    #Aを出力
    print("A")

    #3秒停止
    time.sleep(3)

    print("3")
    #subCをthreadで実行
    ## threadを用意
    thread_2 = threading.Thread(target=subC) 
    ## threadを実行
    thread_2.start()
    #Dを出力
    print("D")
    ```

    ```
    thread_2 = threading.Thread(target=subC) 
    ^
    SyntaxError: invalid character in identifier

    Process finished with exit code 1
    ```
    と上記のようなエラーが出てしまいうまく実行できません
    なにが原因何でしょうか

    キャンセル

  • 2018/05/20 00:31 編集

    coco_bauerさんではありませんが、その行の末尾に全角スペースが入っているのが原因のようです。削除してください
    他に、for文以下をすべてもう1段階インデントし、sunC→subCと変更すると実行可能になりました

    キャンセル

  • 2018/05/20 06:55

    回答有り難うございます
    hayataka2049さんの言う通りに修正しましたら無事実行できました
    ありがとうございました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    4848questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。