48299


マルチプロセスをやってみようと思い、[あるサイト](https://www.quark.kj.yamagata-u.ac.jp/~hiroki/python/?id=15)から引っ張って来たマルチプロセスのコードです。それを私がいくつかprint文を増加させたり、`global`宣言化して、いろいろ挙動を調査して改編してみたものです。  
実行してみると、すんなりと実行できたのですが、関数の中に`print`文を入れて確かめてみると、どうやら関数が全く実行されていない・・・。

文法としてはこれで間違っていないように思うのですが、どこに問題があるのでしょうか？  
関数の中身が変な計算になっているのかと思いましたが、関数自体が実行されていないようなのです。タスクマネージャを見ると、確かにプロセス処理が一時的に増加し、すぐに減少するため、マルチプロセス自体は発生しているように見えます。

関数を実行するのかと思いきや、関数は全く実行されていないように思うのですが、これはどうしてなのでしょうか？別プロセスに入れられているからだと思ったのですが、最終的にnの値を確かめてみても、初期値から変化していないように思います。

これが正常なマルチプロセスの挙動なのでしょうか？まだ初めての事で、どんなものなのかがわかりません。Python公式サイトや、本家SOのQ&Aでは、こうかけと言われているようになっていると思うのですが・・・。

[python3 multiprocess
処理が並行に動いてくれません。](https://ja.stackoverflow.com/a/47494/3060)

上記質問の回答でnekketsuuさんが提示してくださったサンプルコードも同じ反応だったので、マルチプロセス自体の理解を私が十分に出来ていないものなのだと思います。（多分コンピューターの動作自体の理解が不十分？）

これを確かめようと思った動機は、自作アプリのコードにマルチプロセスを取り入れようと思ったところ、Start!Finish!とほぼ同時に打たれてしまい、画面は真っ白だし、空回り感が激しかったので、いきなり大きなプログラムに入れたせいでどっか間違えているんだろうと思っていましたが、こちらも関数内の処理にはいって行っているように思えないため、驚きました。(中身は結構大きな`for`ループを回しているので、もっと時間のかかる処理を期待していたのです。)

**質問**  
マルチプロセスをするのはいいのですが、この関数の中身が実行されているように見えないのですが、どういうことなのでしょうか？普通にグローバルスコープに属するのですが、グローバル宣言までしています。`n`をとっても、`n`は関数外でも値をかえていないように思うのですが、これはどうしてなのでしょうか？（別プロセスで処理したから？）そうすると、結果としてどのような計算を関数内で行ったとしても、その結果を使う事ができないので、絵に描いた餅のように思ってしまいます。

追記：  
OOPerさんのご指摘を受けましたので、自分なりに書いてみます。  
実行環境

[code]

    Windows-10  64bit Intel(R) Celeron(R) CPU G530 @2.40GHz 2.40GHz
    Anaconda3 python 3.6.3
    
[/code]

ソースファイルは、アナコンダにモジュールファイルをいつも通り作って、そしてそれを実行ボタンで実行したものです。シェルとかそういった難し気なことをしたことはないです。ひょっとして、USBメモリから実行していることは影響しているでしょうか？`py`ファイルはUSBメモリ内のコードです。

* * *

**コード**

[code]

    from multiprocessing import Process
    import time
    
    def countDown(n):
        print("来ました",n)
        while n > 0:
            n -= 1
    
    n = int(1e9)
    global n1,n2,n3,n4
    n1, n2, n3, n4 = int(n/4), int(n/4), int(n/4), int(n/4)
    print(n1,n2,n3,n4)
    jobs = [
        Process(target=countDown, args=(n1,)),
        Process(target=countDown, args=(n2,)),
        Process(target=countDown, args=(n3,)),
        Process(target=countDown, args=(n4,)),
        ]
    
    start_time = time.time()
    for j in jobs:
        j.start()
    
    for j in jobs:
        j.join()
    
    finish_time = time.time()
    print(finish_time - start_time)
    print(n1,n2,n3,n4)
    
[/code]

**実行結果**

[code]

    250000000 250000000 250000000 250000000
    0.7248373031616211
    250000000 250000000 250000000 250000000
    
[/code]


CC BY-SA 4.0
2018-09-12T01:37:04.530
48294
2020-05-17T19:48:30.857
2020-05-17T19:48:30.857
19110
24284
question
python python3 spyder python-multiprocessing
multiprocess python 処理がスタートしていないように見える。それはなぜでしょうか。


`print()` が動かないのは、[PicoSushi
さんの回答](https://ja.stackoverflow.com/a/48299/19110)にあるように Spyder
の問題です。しかしこのコードには更に複数の問題があります。

おそらく質問者さんは2つの点について誤解なさっています。

## 1. `global` 文

1 つ目の誤解は、[`global`
文](https://docs.python.org/ja/3/reference/simple_stmts.html#the-global-
statement)についてです。質問文にあるような書き方をしても、グローバルスコープにある変数 `n1` ～ `n4` が書き換わるわけではありません。

`global` 文は、`global`
が置かれたスコープにおいて、その識別子がグローバルスコープのものであるように処理するというものです。グローバルスコープで `global`
しても今回の用途としては意味がありません。

以下は `global` を使ってグローバル変数を書き換えるサンプルコードです。[Wandbox
で動かせます。](https://wandbox.org/permlink/2wAFq59i35ThiCl5)

[code]

    a = None
    
    def set():
        global a
        print("set is called!")
        a = 42
    
    if __name__ == '__main__':
        a = 1
        print("a =", a)  # 1 が出力される
        set()
        print("a =", a)  # 42 が出力される
    
[/code]

## 2. multiprocessing とグローバル変数

2 つ目の誤解は、グローバル変数の書き換えについてです。multiprocessing
を使って新しいプロセスを立ち上げたとき、そのプロセスは元のプロセスとは独立した状態を持っています。グローバル変数はコピーされますが、子プロセスで値を書き換えたとしても親プロセスでの値には反映されません。

参考: [Python multiprocessing global variable updates not returned to
parent](https://stackoverflow.com/a/11056415/5989200) -- Stack Overflow

## 解決法

では multiprocessing を使いながらグローバルなデータを書き換えたいときには、どうすればよいのでしょうか？ multiprocessing
のドキュメント内、[「プロセス間での状態の共有」](https://docs.python.jp/3/library/multiprocessing.html#sharing-
state-between-processes)に解説とサンプルコードが書かれています。

  * 方法A: 共有メモリを使う

> データを共有メモリ上に保持するために Value クラス、もしくは Array クラスを使用することができます。

  * 方法B: サーバープロセスを使う

> `Manager()` 関数により生成されたマネージャーオブジェクトはサーバープロセスを管理します。マネージャーオブジェクトは Python
> のオブジェクトを保持して、他のプロセスがプロキシ経由でその Python オブジェクトを操作することができます。

サーバープロセスについては [How can I recover the return value of a function passed to
multiprocessing.Process?](https://stackoverflow.com/q/10415028/5989200)
の内容も参考になるかもしれません。


CC BY-SA 4.0
2018-09-12T02:54:54.547
48298
2018-09-12T03:01:25.330
2018-09-12T03:01:25.330
19110
19110
48294
answer


本家Stackoverflowにて、Spyder開発者の方がコメントしておられました。

> MultiprocessingはWindowsでは動かないので以下を実行してください。
>
> `Run > Configuration per file > Execute in an external system terminal`  
>  <https://stackoverflow.com/questions/48078722/no-multiprocessing-print-
> outputs-spyder>


CC BY-SA 4.0
2018-09-12T03:03:22.167
48299
2018-09-12T03:03:22.167
2020-06-17T08:14:45.997
-1
29826
48294
answer