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

42

Я могу использовать ~ вместо /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?

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

задан JNing 07.03.2017 в 09:05
источник

4 ответа

45

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

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

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

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

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

    
ответ дан alexis 07.03.2017 в 11:12
источник
30

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

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

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

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

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

  

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

     

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

    
ответ дан Jacob Vlijm 07.03.2017 в 09:19
12

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

Пока он выполняется в:

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=~ (поскольку --prefix is не допустимое имя переменной), а не в cmd "p"refix=~ (из-за этого указано p ) и не в 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 , помните, что вам нужно указать переменные разложения!

    
ответ дан Stéphane Chazelas 07.03.2017 в 12:03
6

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

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

python ptb_word_lm.py --data_path=$HOME/blabla
    
ответ дан Dmitry Grigoryev 07.03.2017 в 11:28