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

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

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

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

Q&A

解決済

2回答

5828閲覧

PythonのCGIのwavファイルの読み込みに関してです。

riekosuzuki

総合スコア11

Python 3.x

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

0グッド

1クリップ

投稿2017/04/29 03:22

編集2017/04/29 07:41

python初心者(python3.5)です。CGIの勉強をしていましてwavファイルの読み込みの方法がどうしてもわかりません。どなたかpythonに詳しい方、ご教示をお願いいたします。
例えば、wavファイルを選択して、そのwavファイルの長さを返したい場合、以下のようにコードを書いたのですが、
実装中に以下のエラーメッセージが発生しました。

##発生している問題・エラーメッセージ

A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred. /Users/rieko/rieko_data/cgi-bin/test1.py in () 22 form = cgi.FieldStorage() 23 wf = form['file'] => 24 length = float(wf.getnframes()) / wf.getframerate() 25 content = length 26 length undefined, builtin float = <class 'float'>, wf = FieldStorage('file', 'call.WAV', b'RIFF$>u\x01WA...x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'), wf.getnframes undefined, wf.getframerate undefined /Users/rieko/.pyenv/versions/3.5.3/lib/python3.5/cgi.py in __getattr__(self=FieldStorage('file', 'call.WAV', b'RIFF$>u\x01WA...x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'), name='getnframes') 583 def __getattr__(self, name): 584 if name != 'value': => 585 raise AttributeError(name) 586 if self.file: 587 self.file.seek(0) builtin AttributeError = <class 'AttributeError'>, name = 'getnframes' AttributeError: getnframes args = ('getnframes',) with_traceback = <built-in method with_traceback of AttributeError object>

###該当のソースコード

python

1 2import wave 3from pylab import * 4import sys 5from pydub import AudioSegment 6import cgi 7import cgitb 8 9cgitb.enable() 10 11html_body = u""" 12<html> 13<head> 14<meta http-equiv="content-type"content="text/html\n"></head> 15<body> 16%s 17</body> 18</html>""" 19 20form = cgi.FieldStorage() 21wf = form['file'] 22length = float(wf.getnframes()) / wf.getframerate() # 波形長さ(秒) 23content = length 24 25 26print ("Content-type: text/html;charset=utf-8\n") 27print ((html_body % content)) 28 29 30<<HTMLファイル>> 31 32<html> 33<head> 34<meta http-equiv="content-type" content="text/html;charset=utf-8"> </head> 35<body> 36 <form action="/cgi-bin/test1.py" method="post" enctype="multipart/form-data"> 入力してください。<br /> 必須 : 37 <input type="file" name="file" /> 38 <button>Send the file</button> 39 40 </form> 41</body> 42</html>

###試したこと
###以下のように、textファイルを選択する場合はうまくいきます。

import cgi import sys import cgitb cgitb.enable() html_body = u""" <html> <head> <meta http-equiv="content-type"content="text/html\n"></head> <body> %s </body> </html>""" form=cgi.FieldStorage() fileitem = form["file"] kek =[] if fileitem.file: linecount = 0 while True: line = fileitem.file.readline() kek.append(line) if not line: break linecount = linecount + 1 content = kek print ("Content-type: text/html;charset=utf-8\n") print ((html_body % content))

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

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

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

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

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

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

KSwordOfHaste

2017/04/29 03:58 編集

コードタグが少々乱れています。```python<改行>プログラムの中身・・・<改行>```と書いてみてください。 --- まだ乱れてますね。プレビュー画面をよくみて、コード範囲が意図通りに表示されることをご確認ください。
guest

回答2

0

ベストアンサー

御質問に提示頂いている元のソースコードで、 wf = form['file'] となっているところを次のように書き換えてみると如何でしょう。一応、手元では動作しているようです。

python

1wf = wave.open(form['file'].file, mode='rb')

KSwordOfHaste さんもご指摘の通り、 cgi.FieldStorage で受け取ったファイルはただのファイルでありバイト列であり、 WAVE ファイル用の機能を有したオブジェクトではありません。そのため、 getnframes()getframerate() といった関数を使いたければ、 import している wave モジュールから wave.open() を呼び出してファイルを解析させ、 wave.Wave_read オブジェクトを得る必要があります。

幸い、 wave.open() はファイル名だけでなく、 File-like オブジェクト (ファイルを単純に open() したときに得られるような、 read()write() を実装したオブジェクト) を引数にとれるので、 cgi.FieldStorage オブジェクトの file プロパティを渡してやれば済むようです。ただ、元の File-like オブジェクトの mode を引き継ごうとして失敗するので、 mode='rb' も明示する必要がありました。このあたり、詳しくは「ファイルオブジェクト」「File-like object (ファイル類似オブジェクト、とも)」などで検索してみると良いかもしれません。

尚、こういった標準ライブラリの使い方については、 CGI 経由でなく、一度インタラクティブシェル (python とだけ入力してた時に立ち上がる対話環境) か、当該機能だけを記述した適当なスクリプトファイルを使って試してみると、動作が分かりやすく学びやすいと思います。

投稿2017/05/04 15:03

argparse

総合スコア1017

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

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

riekosuzuki

2017/05/04 15:50

本当にありがとうございます。 次のようにコードを書き直しましたが、 エラーが出てしまいます。 アドバイスいただきましたように、一度CGI 経由でなく、インタラクティブシェル で基本から学んでみます。 <試したコード> from pylab import * import codecs import os from pydub import AudioSegment import cgi import sys import cgitb cgitb.enable() html_body = u""" <html> <head> <meta http-equiv="content-type"content="text/html\n"></head> <body> <H1>%s</H1> </body> </html>""" form = cgi.FieldStorage() wf = wave.open(form['file'].file, mode='rb') # save file fout = file("tmp/tmp0000.wav", "wb") while True: chunk = wf.read(1024 * 1024 * 10) if not chunk:break fout.write(chunk) wf = wave.open('tmp/tmp0000.wav',"rb") length = float(fout.getnframes()) / fout.getframerate() # 波形長さ(秒 content = length fout.close print ("Content-type: text/html;charset=utf-8\n") print ((html_body % content)) <エラーメッセージ> A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred. /Users/rieko/rieko_data/cgi-bin/test1.py in () 27 # save file 28 #fout = wave.open("tmp/tmp0000.wav", "wb") => 29 fout = file("tmp/tmp0000.wav", "wb") 30 while True: 31 chunk = wf.read(1024 * 1024 * 10) fout undefined, file undefined NameError: name 'file' is not defined args = ("name 'file' is not defined",) with_traceback = <built-in method with_traceback of NameError object>
argparse

2017/05/04 16:15

質問本文の「該当のソースコード」にお書きになっている、いろいろ変に弄る前のソースコードを修正してみてください。
riekosuzuki

2017/05/07 03:59

本当に本当にありがとうございます!!いろいろ変に弄る前のソースコードを修正(wf = wave.open(form['file'].file, mode='rb'))したら、成功しました。 感謝いたします。
guest

0

クライアントからアップロードされたWavファイルをCGIで解析する処理ですが、cgiモジュールで取得できるファイルデータform['file']は単なるバイナリーデータの羅列でそれをwaveデータとしては扱えません。一旦サーバー上にWAVファイルとしてセーブしてから改めてwaveモジュールのopenメソッドを使ってwaveオブジェクトを生成しないといけないようですね。

ここのサンプルに、cgiでフォームから取り出したバイナリーデータをWAVファイルとしてセーブするサンプルがあります。

上記を参考に、一旦サーバー上の一時ファイルへWAVファイルを格納し、その後waveオブジェクトを生成し、フレームレートやフレーム数を取り出すといった部分のみコードを書いてみました。

python

1... 2waveFile = form['file'] 3# save file 4fout = file("tmp/tmp0000.wav", "wb") 5while True: 6 chunk = waveFile.file.read(1024 * 1024 * 10) 7 if not chunk: 8 break 9 fout.write(chunk) 10fout.close() 11//これでサーバーの'tmp/tmp0000.wav'にWAVファイルができている 12wf = wave.open('tmp/tmp0000.wav') 13length = float(wf.getnframes()) / wf.getframerate() # 波形長さ(秒 14...

上記はformにfileが指定されていなかった場合のエラーチェックなどは省略しています。CGIをテストできる環境がないため間違いなどありましたらご容赦ください。

投稿2017/04/29 08:17

編集2017/04/29 08:29
KSwordOfHaste

総合スコア18394

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

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

riekosuzuki

2017/04/29 10:44 編集

本当にありがとうございます。 コードを試してみたのですが、以下のようなエラーがでてしまいました。 サーバーはcgiserver.pyでたてています。 cgi-bin-------test1.py | cgiserver.py test1.html レンタルサーバーにする必要があるのでしょうか? <エラー表示> A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred. /Users/rieko/rieko_data/cgi-bin/test1.py in () 31 waveFile = form['file'] 32 # save file => 33 fout = file("tmp/tmp0000.wav", "wb") 34 while True: 35 chunk = waveFile.file.read(1024 * 1024 * 10) fout undefined, file undefined NameError: name 'file' is not defined args = ("name 'file' is not defined",) with_traceback = <built-in method with_traceback of NameError object>
KSwordOfHaste

2017/04/29 11:12

はっきりしたことは分かりませんが、cgiserver.pyはHTML内にかかれているformのfileに実際にアップロードしようとするWAVファイルを「ユーザーがブラウザー上でfileボタンを押してアップロードファイルを指定する」のと同じようにアップロードしてくれる機能を持っているのでしょうか? 自分はcgiserver.pyについて知らないのです><
KSwordOfHaste

2017/04/29 11:28 編集

む、自分がサンプルページのコードを読みそこなったのかもです。 if waveFile.file: fout = file("tmp/tmp0000.wav", "wb") とかかれているのでif文のところが必要なのかも。 --- すみません、上の推測はあってるようには思えませんでした。 fout = file("tmp/tmp0000.wav","wb") が問題なのですが、これは参考にしたサイトのコードそのものです。しかし自分にはこの'file'の意味がわかりませんでした。fileではなくopenに変えればわかるのですが。openに変えてみたら動く気がします。 fout = open("tmp/tmp0000.wav", "wb")
riekosuzuki

2017/05/01 12:49 編集

大変ありがとうございます。ご紹介いただいたサンプルのコードを私も見ていたのですが、意味がさっぱりわかりませんでした。しかし、今回のいただいた解説でよくわかりました。また、 アップロード機能について調べてみます。fout = open("tmp/tmp0000.wav", "wb")は、試してみたのですがダメでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問