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

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

ただいまの
回答率

90.10%

[Python] importしたモジュール内の変数が使えない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,342

Yukiya025

score 78

 実行環境

  • Cloud9
  • Windows7
  • Python 2.7

 困っていること

  • 同じ階層にあるextract.pyをjavascript_kindle.pyにimportしても、そのモジュール内の変数 (filelistnameとindex) がなぜか片方 (index) 使えない。
  • importしたモジュール内の変数indexを使う行で Undefined valuable "index"と出る (赤い×印の行)
    フォルダ構造
    ×がついた画面 (javascript_kindle.py)
# extract.py
# -*- coding:utf-8 -*-
# codesフォルダのファイル名を取得
# [_]以降のファイル名を取得
# print() する
import os
# ファイルパスも文字列!
# basename = os.path.basename("./codes") codesとフォルダ名が返ってきた

def extract_last():
    filelist = os.listdir("./codes")
    global filelistname 
    filelistname = filelist[0]
    # [_]以降のファイル名を取得
    global index 
    index = filelistname.find('_')
    print(filelistname)
    print(str(index))
    print(filelistname[index:]) # 2番目から末尾までの文字を取り出す
# javascript_kindle.py
# -*- coding:utf-8 -*-

import os
import extract
files = os.listdir('./codes')
filenum = len(files) + 1

with open('./output.txt', 'w+') as f:
    for i in range(1, filenum):
        file_data = open('./codes/page' + str(i) + extract.filelistname[index:], 'r')
        # スラッシュの数は24個
        # ''""の使い分け: どちらでもよいが、どちらかに統一
        f.write('////////////////////////\n//page' + str(i) + extract.filelistname[index:] + '\n' + file_data.read() + '\n')

 試したこと (しかしうまくいかない)

よろしくお願いしますm(_)m

 できました! ありがとうございます(≧∀≦)

umyu様、ありがとうございますヽ(゚▽゚*)乂(*゚▽゚)ノ

# extract.py
# -*- coding:utf-8 -*-

import glob
import os

filelistname = ""
index = 0
def extract_files(path, ext):
    for file_name in sorted(glob.glob(path + "/*" + ext)):
        print(file_name) # ./codes/page1_script.js
        yield file_name
# javascript_kindle.py
# -*- coding:utf-8 -*-

import os
import extract
files = os.listdir('./codes')
filenum = len(files) + 1

with open('./output.txt', 'w+') as f:       
    for file_name in extract.extract_files("./codes", ".js"):
        with open(file_name, 'r') as file_data:
            f.write('/' * 24 + '\n//' + os.path.basename(file_name) + '\n' + file_data.read() + '\n')
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

def extract_last():
    filelist = os.listdir("./codes")
    global filelistname 
    filelistname = filelist[0] # extract_last関数の呼び出しのこの行でグローバル変数が定義される。


extract.pyは変数:filelistnameをモジュールレベルで定義していなく かつ javascript_kindle.pyextract_lastの呼び出しを行っていないため、global(モジュールレベル)で変数定義できてないです。

◇対応案
案1,extract_last関数を呼び出してから変数を使用する。
案2,モジュールレベルで変数を先に定義しておく。

※スクリプトのやりたいことがよく分かりませんが、extract_last関数のreturnで値を返すのはだめなのでしょうか?

案2の対応です。
extract.py

filelistname = "" # PEP8に従うのなら、変数名は大文字で。
index = 0 # 
def extract_last():
    # 以下省略


javascript_kindle.py

# 変数:indexにモジュール名(extract)が付いていないので追加
file_data = open('./codes/page' + str(i) + extract.filelistname[extract.index:], 'r')


◇参考情報
global 文


Pythonのバージョンが分かりませんでしたので、バージョンに限定されない書き方にします。
失礼しました、質問文にバージョン2.7と書いてありました。
モジュールの事はまず忘れてください。まず一連のファイル名を取得する関数を作ります。
拡張子を指定してファイル一覧を取得にはglob.globが使えます。
◇参考情報
Pythonでフォルダ内のファイルリストを取得する

import glob
import os

def extract_files(path, ext):
    """
    :params path 検索フォルダ
    :params ext 拡張子
    """
    for file_name in sorted(glob.glob(path + "/*" + ext)):
        # 同じ拡張子で除外したいファイルがもしあれば、この位置でif文で判断してください。
        print(file_name)
        # ファイル名を1個ずつyieldで返す。
        yield file_name

# 呼び出し方法
print(list(extract_files("./codes", ".js")))

次にこの関数を使ってforループで回します。

with open('./output.txt', 'w+') as f:
    for file_name in extract_files("./codes", ".js"):
        print("/" * 24)
        print(file_name)
        print(os.path.basename(file_name))

その後、上記関数をextract_files関数をextract.pyに記述を移し、javascript_kindle.pyextract_filesの呼び出し部分をextract.extract_filesに変更します。
この手順でモジュール化ができます。


以下はサンプルコードです。
extract.py

# -*- coding: utf-8 -*-
import glob


def extract_files(path, ext):
    """
    :params path 検索フォルダ
    :params ext 拡張子
    :return ファイル名
    """
    for file_name in glob.iglob(path + "/*" + ext):
        print(file_name)
        yield file_name


def main():
    print(list(extract_files("./codes", ".js")))


if __name__ == "__main__":
    main()


javascript_kindle.py

# -*- coding: utf-8 -*-
import os
import extract


def main():
    with open('./output.txt', 'w+') as f:
        for file_name in extract.extract_files("./codes", ".js"):
            with open(file_name, 'r') as file_data:
                f.write('/' * 24 + '\n//page//' + os.path.basename(file_name) + '\n' + file_data.read() + '\n')


if __name__ == "__main__":
    main()

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/03 20:10 編集

    umyu様
    第二の案を採用し、コードを修正し赤い×印は消えました! ありがとうございます(≧∀≦)

    しかし `IOError: [Errno 2] No such file or directory: './codes/page1'` とエラーが出ています。
    `filelistname[index:]` (extact.py) と
    `extract.filelistname[extract.index:]` (javascript_kindle.py) の中に何もデータが入っていないようです。
    どうすれば入るようになるでしょうか(?_?)

    ちなみに、このコードは[[実際のコード付き by Python] Progateからダウンロードしたコードをkindleで読みたい!](https://qiita.com/Yukiya025/items/c80b143427ceaa343c22) (複数のファイルの内容を一つのファイルにまとめる)ことを目的に作っています。
    codesフォルダの中にpage1_script.js...とファイル名が数字の部分のみが変わっていくので、「_script.jsの部分も自動でPythonが取ってくるように改良しよう (Progateのコースはほかに_script.rbなどがあるので)」と思いついたはいいもののglobal変数ではまっていますorz


    修正したコード↓

    ```python:extract.py
    # extract.py
    filelistname = ""
    index = 0
    def extract_last():
    filelist = os.listdir("./codes")
    print(filelist)
    global filelistname
    filelistname = filelist[0] # extract_last関数の呼び出しのこの行でグローバル変数が定義される。
    # [_]以降のファイル名を取得
    index = filelistname.find('_')
    print(filelistname[index:])
    ```


    ```python:javascript_kindle.py
    # javascript_kindle.py
    files = os.listdir('./codes')
    filenum = len(files) + 1

    with open('./output.txt', 'w+') as f:
    for i in range(1, filenum):
    print(extract.filelistname[extract.index:])
    # 変数:indexにモジュール名(extract)が付いていないので追加
    file_data = open('./codes/page' + str(i) + extract.filelistname[extract.index:], 'r')
    f.write('////////////////////////\n//page' + str(i) + extract.filelistname[extract.index:] + '\n' + file_data.read() + '\n')
    ```


    ヒントをいただけたのに自分で解決できないのが悔しく、回答をお願いするのも2度目で心苦しいのですがまたヒントをいただけないでしょうか(>_<)

    キャンセル

  • 2018/08/05 07:39

    ありがとうございますm(;∇;)m
    ファイル名を取得する関数、forループの書き方、サンプルコードをずっと画面上で見ているとコードが右から左に滑りだしたので (末期) Atomにexport-htmlパッケージをインストールして印刷しました。
    (↑Atomに印刷機能が標準装備されていないことを今回初めて知るw)
    ボールペンでumyu様の指示をコード横に書き込んでやっと理解できてコードに落とし込めました!!!

    もともと長々とPC画面を見るのがつらいしモバイルルーター持ってないしでコードをkindleで読めるように、覚えたてのPython@Progateでばらばらになっているファイルを自動でひとつにするプログラムを書こうとしてどこが悪いのかわからずでも動いてくれないのはよくわかるという状態だったので本当に助かりました (T_T)
    これでkindleをよりフル活用できる。。。(v≧∇≦)v


    完成したコードはコメント欄ではなく質問文に載せました。
    (コメント欄ではマークダウンが使えない? ため)

    キャンセル

  • 2018/08/05 15:03

    @Yukiya025さんへ
    解決してよかったですー。
    解決方法のまとめありがとうございました。

    キャンセル

  • 2018/08/05 20:47

    いえいえ、こちらこそxD ありがとうございます(≧∀≦)

    キャンセル

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

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

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