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

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

新規登録して質問してみよう
ただいま回答率
85.35%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

パス

パス(path)はファイルシステムの場所(階層)を明示したものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1535閲覧

(Python) 別のディレクトリにあるファイルをopenできない ※モジュールとして実行する場合

masatoemata

総合スコア7

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

パス

パス(path)はファイルシステムの場所(階層)を明示したものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/09/26 12:52

編集2021/09/26 13:02

パス指定について度々質問を投稿してしまい,本当に申し訳ないのですが,
下記エラーが発生する背景をご教示いただけますと幸いです。。

FileNotFoundError: [Errno 2] No such file or directory

「ファイル操作における相対ディレクトリの起点は、カレントディレクトリである」ということを念頭に置いて,ファイル取得を行うコードを書きました。具体的には,カレントディレクトリや実行ファイルパスに影響が出ないようにカレントディレクトリを「os.chdir」により固定しています。それにも関わらず,なぜエラーが発生するのでしょうか?

#ファイルをうまく取得できるケース
下記のようなディレクトリ構造においてファイルを実行したとき,ファイルをうまく取得できました。
※ちなみにこれは,前回の質問「(Python) 別のディレクトリにあるファイルをopenできない」が解決した成果です。

projectX |_apps ★ファイル実行時点のカレントディレクトリ=ファイル取得時点のカレントディレクトリ |_configurator.py ★実行ファイル |_users |_demo |_config.yml ★欲しいファイル

python

1# ~/projectX/apps カレントディレクトリ 2# $configurator.py 実行ファイルパス 3 4class Configurator: 5 @classmethod 6 def user_config(cls, user_name): 7 os.chdir(os.path.dirname(os.path.abspath(__file__))) #カレントディレクトリをこのファイル自身のディレクトリに移動 8 print(os.getcwd()) # C:\Users\masat\projectX\apps がいつでも出力される 9 config_path = f'../users/{user_name}/config.yml' 10 with open(config_path, "r", encoding='utf-8') as yaml_file: 11 ... 12 13if __name__ == "__main__": 14 config = Configurator.user_config("demo") 15 print(config) 16

#ファイルをうまく取得できないケース
####①カレントディレクトリは同じ,かつ,異なるパスにあるファイルを実行した場合
上記「configurator.py」をモジュールとして使う別ファイルを実行すると,ファイル取得(open)ができず「FileNotFoundError」が発生しました。

projectX |_apps ★カレントディレクトリ=ファイル取得時点のカレントディレクトリ |_configurator.py ★モジュールとして利用 |_bigquery_app |_base.py ★実行ファイル |_users |_demo |_config.yml ★欲しいファイル

python

1# ~/projectX/apps カレントディレクトリ 2# $bigquery_app/base.py 実行ファイルパス 3 4os.chdir(os.path.dirname(os.path.abspath(__file__))) 5sys.path.append('..') #これはimportのパスの起点には影響するがファイル取得(カレントディレクトリ)には影響しない※前回の質問でご教示いただいた内容 6from configurator import Configurator 7class BigqueryBase: 8 def __init__(self, ...): 9 ... 10 self.config = Configurator.user_config(user_name)['system'] # configurator.pyのwith open() を実行 11 ...

####②カレントディレクトリが異なるファイルを実行した場合
当然のように下記の場合も同様のエラーが出ました。

projectX |_apps ★ファイル取得時点のカレントディレクトリ |_configurator.py ★モジュールとして利用 |_bigquery_app ★ファイル実行時点のカレントディレクトリ |_base.py ★実行ファイル |_users |_demo |_config.yml ★欲しいファイル

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

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

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

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

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

quickquip

2021/09/26 23:40 編集

なぜsys.path.appendやos.chdirみたいな飛び道具で解決しようとしているのか? がよくわかってなくて、そういう飛び道具的,外道的な手段が使えるようになりたいということなのか、こういう構造でどうすると動かせるようになるのか知りたいということなのか、そのあたりの質問の根本的趣旨がよくわからなかったです。(感想ですが)
bsdfan

2021/09/27 02:08 編集

プログラムの最初で決めた場所にchdirして、あとはそこからの相対パスで動くように作れば簡単だと思うのですが、今のやり方にこだわりがありますか? カレントディレクトリの移動はいろんなところに影響するので、むやみにやるべきことではないです。現状の混乱もそこに起因していると思われます。
masatoemata

2021/09/27 05:21

@quickquip さん コメントありがとうございます。 いろいろ試してるうちに「os.chdir」をコードに追加してみていましたが, 本当は基本に忠実に,シンプルに解決したいです。なのでこちらの趣旨になります。 >こういう構造でどうすると動かせるようになるのか知りたいということなのか
masatoemata

2021/09/27 05:24

@bsdfan さん 基本方針について重要なアドバイスをくださりありがとうございます。 今のやり方にこだわりはないので,混乱のもとを潰してみます。 できたら結果報告します!
masatoemata

2021/09/27 13:29

@bsdfan さん プログラムの最初で決めた場所にchdirして、あとはそこからの相対パスで動くように作りました! ※コードをシンプルにできたので,原因も特定しやすくなりました。お恥ずかしい話ですが,パスがあたらないのは下記「{user_name}」の引数が微妙に実際のディレクトリ名と違う文字列になっていたからでした。 config_path = f'../users/{user_name}/config.yml'
guest

回答2

0

自己解決

「質問への追記」でいただいたアドバイスをきっかけに解決したので記入します。

quickquip
2021/09/27 08:40
なぜsys.path.appendやos.chdirみたいな飛び道具で解決しようとしているのか? がよくわかってなくて、そういう飛び道具的,外道的な手段が使えるようになりたいということなのか、こういう構造でどうすると動かせるようになるのか知りたいということなのか、そのあたりの質問の根本的趣旨がよくわからなかったです。(感想ですが)

bsdfan
2021/09/27 11:07
プログラムの最初で決めた場所にchdirして、あとはそこからの相対パスで動くように作れば簡単だと思うのですが、今のやり方にこだわりがありますか?
カレントディレクトリの移動はいろんなところに影響するので、むやみにやるべきことではないです。現状の混乱もそこに起因していると思われます。

  • 複数のファイルそれぞれでカレントディレクトリを指定するのではなく,最初で決めたファイルでのみ指定して、あとはそこからの相対パスでファイルを取得するシンプルな構成にしました。
  • コードをシンプルにできたので,原因も特定しやすくなりました。お恥ずかしい話ですが,パスがあたらないのは下記「{user_name}」の引数が微妙に実際のディレクトリ名と違う文字列になっていたからでした(申し訳ございません)。

config_path = f'../users/{user_name}/config.yml'

  • 今後飛び道具での解決に逃げないよう,基本を抑えるよう精進します。

投稿2021/09/27 13:37

編集2021/09/27 13:46
masatoemata

総合スコア7

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

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

0

plain

1importされたファイルの中で__file__を参照した場合、 2__file__はimportされたファイルのpathではなく、 3pythonコマンドの引数として与えられたファイルのpathです。 4 5そのため、質問に書かれたような動作になります。

_configurator.pyの中に、

python

1print(__file__)

を追加して実行してみればすぐにわかることです。

投稿2021/09/26 14:13

編集2021/09/26 14:17
ppaul

総合スコア24670

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

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

masatoemata

2021/09/27 05:18

ご教示ありがとうございます。いただいた方法で動作の流れを確認してみます! いろいろ理解したらまたコメントしますm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問