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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Bottle

Bottleは、PythonのWebサーバです。1つのPythonファイルで構成されており、非常に軽量。Web APIの作成や導入が簡単で、DjangoやFlaskに比べ使いやすくシンプルなことが特徴です。

Python 3.x

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

716閲覧

bottleの実行中にファイルダイアログを開きたい

退会済みユーザー

退会済みユーザー

総合スコア0

Bottle

Bottleは、PythonのWebサーバです。1つのPythonファイルで構成されており、非常に軽量。Web APIの作成や導入が簡単で、DjangoやFlaskに比べ使いやすくシンプルなことが特徴です。

Python 3.x

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2018/08/13 04:47

bottleのローカルサーバーを利用した、ローカルアプリを作っています(ブラウザで稼働)。

ローカルにあるファイルを取得して利用する処理を実装しようとしているのですが、
途中で、ユーザーにフォルダやファイルの場所を選択してもらおうと思っています。

それでブラウザ上の操作によって、ファイルダイアログを開きたいです。
そのために以下のようなものを作ってみました。

python

1import tkinter,tkinter.messagebox,tkinter.filedialog 2 3@route('/dialog') 4def dialog(): 5 6 7 root = tkinter.Tk() 8 root.withdraw() 9 10 fTyp=[("","*")] 11 fnames=tkinter.filedialog.askopenfilenames(filetypes=fTyp)

URLに対して、tkinterを使ったファイルダイアログを割り当てました。
そのURLにアクセスしたらファイルダイアログを開くようにしたいという考えです(実際にはajaxを併用します)。

しかし上記のようにしてみたところ、なんの反応もなく、ダイアログは開きません。
上記のコード自体は普通にローカルで実行すれば正常に動作します。

どこが問題なのでしょうか。
ご指導お願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

恐ろしく遅くなりましたが、解決しました。

1 モジュール呼び出しならOK
bottleのメインプログラム内に直接tkinterのコードを書くと、ダイアログが出ませんでした。
しかしモジュール内にtkinterのコードを書き、それをインポートして呼び出すと問題無く動きました。
理屈がよく分かりませんが、これが一番簡単な解決かもしれません。

2 subprocessもOK
上記に気付かず、先にsubprocessを使う方法を試しました。これでもファイルダイアログを動かすことができました。
もしかしたら利用場面があるかもしれませんし、せっかくなので載せておきます。

subprocessとして、tkのファイルダイアログを作ります。取得したパス(文字列)はprintで戻します。
bottle側からは、Popenでsubprocessを動かし、printされた結果を受けとります。

相対パスだとうまく動きませんでした。

bottle側

python

1import subprocess as sbp 2proc = sbp.Popen(["python",r"fullpath-----xxx.py"],shell=True,stdout=sbp.PIPE,stderr=sbp.PIPE) 3out,err = proc.communicate()

subprocess側

python

1import tk 2import tkinter.filedialog as tkfdg 3 4root = tk.Tk() 5root.withdraw() 6dir = tkfdg.askdirectory() 7print(dir)

★追記★
その後あれこれやっていたところ、上記の方法でも不安定なことが分かりました。動かないことがあります。
最終的にはファイルを分けて、
os.startfile
を使うと間違いなく起動するようです。
この場合完全に別のプロセスとして動いてしまいますが、一応の目的は達成できます。

★追記2★
wxpythonを使うと全く問題無く作動しました。tkの特性なのでしょうか。

投稿2018/10/07 11:26

編集2018/10/29 09:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

[ブラウザ] <= HTTP => [サーバー]
bottleはサーバー側で動きます。

質問文の動作を行いたい時は、htmlを生成して<input type=”file”>タグでファイルを選択して、
アップロードする形に変更してくださいな。

投稿2018/08/13 04:59

編集2018/08/13 05:04
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/13 14:22 編集

ありがとうございます。実は、アップロードの方法を一応試したのですが、そこで問題が起きました。 ・ファイルをbase64に変換 ・ajaxで送信 ・bottleで受けとり、デコードしwriteして、然るべきフォルダに保存 というところまでは一応できました。 ただ、その後数十MBのファイルを送信したところ、ブラウザでエラーのような表示が出てそれ以上進みませんでした(要件上、大容量ファイルを扱うことが必須になります)。 以上のことから、「そもそもローカルでやってるんだから、ローカル側で直接動作させることはできないか? そのほうが早いし色々できるのでは」と思って、ファイルダイアログを試し始めたところです。 こういう状況なのですが、そもそも発想が間違っているでしょうか?
umyu

2018/08/13 15:16 編集

@qwdcf_magさんへ 既に試したことがあるのでしたら、最初から質問文にその旨を記載して頂けると2度手間回答が防げるのでありがたいです。 1,10MBのファイルを送信 「bottle body max upload size」でググるとbottle.Request.MEMFILE_MAXがヒットします。 bottle.Request.MEMFILE_MAX = 大きい数字 みたいな感じで。公式ドキュメントは以下です。 https://bottlepy.org/docs/dev/api.html#bottle.BaseRequest 2,>発想が間違っている bottleはHTTPサーバーなので制約あります。 ・HTTPとブラウザで実現可能な事しかできない。 ・クライアントとbottleサーバーが別PCだと仮定すると動作が理解しやすいのでは。 ・サーバー側でブロックする処理は避けるべき。 今回の場合は、ファイル選択のダイアログ表示と選択処理。 >ローカル側で直接動作させることはできないか? うーん、「bottleのローカルサーバーを利用した、ローカルアプリ」が開発要件にあるのに、 それだとすると、bottleのローカルサーバーを利用する意味がないのでは・・・
退会済みユーザー

退会済みユーザー

2018/08/14 00:04 編集

>bottle.Request.MEMFILE_MAX こちらのほう、設定できました! ひとまず1GBにしました。 >エラー状況 現象について再度確認したのですが、70MBのファイル単体が正常にアップロードできることが分かりました。 しかし 300MB1つ や 50MB規模のもの多数 というアップロードをすると、ブラウザ(chrome)側でエラーが出ました→Debugging connection was closed.Reason :Render process gone.(これについては別質問たてたほうがいいかもしれませんが)。 >ローカル側のファイル取得ができないものか 以上のような状況ですが、私の発想としては ・アップロード形式をとると、ファイルの受け渡し(エンコード、デコードと書き込み)で結局かなり処理時間がかかってしまう(数十MBで数秒) ・サーバーとクライアントが理屈上は別PCだという認識は一応あるのですが、 ローカルなので、物理的なHDDは同じである → 結局のところサーバーの外のディレクトリからサーバー領域内のディレクトリにファイルを持ってくる処理である → shutilとかを使ってダイレクトに動かすほうがきっと早い & ファイルダイアログが動かないという理由は思い付かなかった → この部分だけはローカルのファイルダイアログを使って処理できたら嬉しい (開発要件→個人で作っているので、外からの縛りはありません。もともと、UIなどの関係でブラウザを借りたいというところに結構大きな動機がありました(きれいにデザインしやすい気がした。あと、簡単にウィンドウ増やせたり)。かなり作ってしまったので今更戻れるかという問題はあります) 以上のようなことで、ファイルダイアログを動かしたい、という考えに至っています。長々申し訳ありません。
umyu

2018/08/14 01:42 編集

@qwdcf_magさんへ うーん、あまりお役に立てそうになさそうなので、解答欄の質疑応答を質問文に反映して他の回答者を待って頂くか、いっその事ツイッターなど他のサイトで聞いてみたほうがレスが付きやすいかもしれません。
退会済みユーザー

退会済みユーザー

2018/08/14 02:57

ご丁寧にありがとうございます!
退会済みユーザー

退会済みユーザー

2018/08/14 04:09

当初の想定からは少し迂回策にはなるのですが、フォームを使った普通のアップロードを利用すると、1GB超えでも、Debugging connection was closed.Reason :Render process gone.は起きませんでした。この方向で少し模索してみたいと思います。
umyu

2018/08/14 04:19 編集

@qwdcf_magさんへ 少しだけ考えてみましたが、結局の所、ブラウザのセキュリティでアップロードのファイルのフルパス(ファイル名は取れるはずです)が取得できないので、そこをどう対応するのかが問題ではないかと。 日本語資料があまりないと思いますが、Electron pythonでググるといろいろヒットするかもです。
退会済みユーザー

退会済みユーザー

2018/08/15 09:04

ありがとうございます! Electronも勉強してみたいと思います。 最終的には new Form で取得したデータを、そのままajaxで送信するやり方(オーソドックスな方法)を使うと、エラーが起きませんでした。かつ、処理速度もそれなりに高速で体感上、問題の無いレベルでした。今のところはこれで行こうと考えています。(ajax時にbase64を使うとパフォーマンスが顕著に悪化&容量次第でエラーが起きるということが分かりました。またPDFをembedしたのですが、DataUrlは描画がかなり重かったのに対し、普通のリンクは重さを感じさせませんでした。「埋め込むほうが早いだろう」と単純に考えたのですが、どうも違ったようです。base64の勉強にもなったのでそれはそれでよかったのですが・・・)
umyu

2018/08/15 09:58

@qwdcf_magさんへ ajaxというキーワードで思い出しましたが、bottleはデフォルトだと非スレッドサーバーです。 ajaxと通常のform送信が重なると処理がブロッキングしてその点がボトルネックになるかもです。 もし変更していなければ、以下のページを参考にしてくださいな。 https://bottlepy.org/docs/dev/deployment.html あともしよろしければなのですが、この件が解決したら、 まとめみたいな内容を自己解決で投稿して頂けると後からこのQAを見た人が参考になるかとー。
umyu

2018/08/15 10:08 編集

bottleで出来るかどうかは分かりませんが。 ファイルアップロード用に@routeを1個切って、ポート番号も別に割り当ててサーバー起動し アップロードファイルの保存時にファイルのハッシュ値(SHA系)を同時に計算し、 ajaxの戻り値として返すこんな感じです。 算出したハッシュ値は紐付けキーとして使用するみたいな。 まあ、他にもいろいろ方法はあると思うので、 パフォーマンスが気になりだしたら調査してみる事をお勧め致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問