Почему я не мог использовать '~' вместо '/ home / username /' при предоставлении пути к файлу

Я могу использовать ~ вместо /home/username/ чтобы указать путь к файлу, когда, например, распаковывает .zip файл.

Однако сегодня, когда я следил за тем же способом, чтобы запустить пример RNN в терминале, был tensorflow.python.framework.errors_impl.NotFoundError .

 $ python ptb_word_lm.py --data_path=~/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/simple-examples/data/ --model=small I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcublas.so.8.0 locally I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcudnn.so.5 locally I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcufft.so.8.0 locally I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcuda.so.1 locally I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcurand.so.8.0 locally Traceback (most recent call last): File "ptb_word_lm.py", line 374, in <module> tf.app.run() File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 44, in run _sys.exit(main(_sys.argv[:1] + flags_passthrough)) File "ptb_word_lm.py", line 321, in main raw_data = reader.ptb_raw_data(FLAGS.data_path) File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 73, in ptb_raw_data word_to_id = _build_vocab(train_path) File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 34, in _build_vocab data = _read_words(filename) File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 30, in _read_words return f.read().decode("utf-8").replace("\n", "<eos>").split() File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/lib/io/file_io.py", line 106, in read self._preread_check() File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/lib/io/file_io.py", line 73, in _preread_check compat.as_bytes(self.__name), 1024 * 512, status) File "/home/hok/anaconda2/lib/python2.7/contextlib.py", line 24, in __exit__ self.gen.next() File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/errors_impl.py", line 469, in raise_exception_on_not_ok_status pywrap_tensorflow.TF_GetCode(status)) tensorflow.python.framework.errors_impl.NotFoundError: ~/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/simple-examples/data/ptb.train.txt 

Затем я заменил ~ на /home/username/ , и он работал правильно.

Почему я не мог использовать ~ вместо /home/username/ для указания пути к файлу при запуске примера RNN?

Не могли бы вы рассказать мне подробно?

Вам нужно понять, что ~ обычно расширяется оболочкой; программы, которые вы вызываете, никогда не видят этого, они видят полный путь, как вставленный bash. Но это происходит только тогда, когда тильда находится в начале аргумента (и не цитируется).

Если программа Python, на которой вы работаете, использует такой модуль, как getopt для синтаксического анализа своей командной строки, вы можете указать аргумент опции --data-path как отдельное «слово», чтобы разрешить расширение тильды:

 $ python ptb_word_lm.py --data_path ~/anaconda2/lib/python2.7/... 

В вашем собственном коде вы можете использовать getopt или argparse для обработки аргументов, а также вручную развернуть тильды, как это предложил @ JacobVlijm.

PS. Тильда также расширяется в начале выражения присваивания переменной оболочки, такого как DIRNAME=~/anaconda2 ; хотя тильда в вашем вопросе также соответствует знаку равенства, это использование не имеет особого значения для оболочки (это просто что-то передается программе) и не вызывает расширение.

Расширение тильды в python

Ответ короткий и простой:

python не расширяется ~ если вы не используете:

 import os os.path.expanduser('~/your_directory') 

См. Также здесь :

os.path.expanduser (путь)
В Unix и Windows верните аргумент с исходным компонентом ~ или ~ пользователя, замененным домашним каталогом этого пользователя.

В Unix начальная ~ заменяется переменной среды HOME, если она установлена; в противном случае домашний каталог текущего пользователя просматривается в каталоге паролей через встроенный модуль pwd. Исходный ~ пользователь просматривается непосредственно в каталоге паролей.

Расширение Тильды выполняется только в нескольких контекстах, которые немного отличаются между оболочками .

Хотя это выполняется в:

 var=~ 

Или

 export var=~ 

в некоторых оболочках. Это не в

 echo var=~ env var=~ cmd ./configure --prefix=~ 

в оболочках POSIX.

Он находится в bash хотя не в режиме соответствия POSIX (например, когда он называется sh , или когда POSIXLY_CORRECT находится в среде):

 $ bash -c 'echo a=~' a=/home/stephane $ POSIXLY_CORRECT= bash -c 'echo a=~' a=~ $ SHELLOPTS=posix bash -c 'echo a=~' a=~ $ (exec -a sh bash -c 'echo a=~') a=~ 

Однако это только тогда, когда то, что находится слева от символа = имеет форму неопределенного допустимого имени переменной, поэтому, хотя оно будет расширено в cmd prefix=~ , оно не будет в cmd --prefix=~ (as --prefix is not допустимое имя переменной), а также в cmd "p"refix=~ (из-за этого цитированного p ) или в var=prefix; cmd $var=~ var=prefix; cmd $var=~ .

В zsh вы можете установить параметр magic_equal_subst для ~ для расширения после любого неуказанного = .

 $ zsh -c 'echo a=~' a=~ $ zsh -o magic_equal_subst -c 'echo a=~' a=/home/stephane $ zsh -o magic_equal_subst -c 'echo --a=~' --a=/home/stephane 

В случае ~ (в отличие от ~user ) вы можете просто использовать $HOME вместо:

 cmd --whatever="$HOME/whatever" 

~ расширяется до значения $HOME . Если $HOME не задано, поведение меняется между оболочками. Некоторые оболочки запрашивают пользовательскую базу данных. Если вы хотите принять это во внимание, вы можете сделать (и это также то, что вам нужно было бы сделать для ~user ):

 dir=~ # or dir=~user cmd --whatever="$dir/whatever" 

В любом случае, в оболочках, отличных от zsh помните, что вам нужно процитировать переменные разложения!

~ имеет особые правила расширения, которые ваша команда не удовлетворяет. В частности, он расширяется только при некотировании, либо в начале слова (например, python ~/script.py ), либо в начале назначения переменной (например, PYTHONPATH=~/scripts python script.py ). У вас есть --data_path=~/blabla который является одним словом в терминах оболочки, поэтому расширение не выполняется.

Непосредственное исправление заключается в использовании переменной оболочки $HOME , которая следует за правилом регулярной переменной расширения:

 python ptb_word_lm.py --data_path=$HOME/blabla