Pourquoi ne puis-je pas utiliser '~' au lieu de '/ home / nom d'utilisateur /' lorsque je donne le chemin du fichier

42

Je peux utiliser ~ au lieu de /home/username/ pour désigner un chemin de fichier lorsque, par exemple, vous décompressez un fichier .zip .

Cependant, aujourd'hui, lorsque j'ai suivi la même procédure pour exécuter un exemple RNN en terminal, tensorflow.python.framework.errors_impl.NotFoundError a été lancé.

$ 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

Ensuite, j'ai remplacé ~ par /home/username/ et cela a fonctionné correctement.

Pourquoi ne puis-je pas utiliser ~ au lieu de /home/username/ pour pointer sur le chemin du fichier lors de l'exécution d'un exemple RNN?

Pouvez-vous me dire en détail?

    
posée JNing 07.03.2017 - 09:05
la source

4 réponses

45

Vous devez comprendre que ~ est normalement développé par le shell; les programmes que vous appelez ne le voient jamais, ils voient le chemin complet comme inséré par bash. Mais cela ne se produit que lorsque le tilde est au début d'un argument (et n'est pas cité).

Si le programme Python que vous exécutez utilise un module tel que getopt pour analyser sa ligne de commande, vous pouvez donner l'argument de l'option --data-path comme un "mot" séparé pour autoriser le développement du tilde:

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

Dans votre propre code, vous pouvez utiliser getopt ou argparse pour le traitement des arguments. Vous pouvez également développer manuellement les tildes en suivant la réponse de @ JacobVlijm.

PS. Le tilde est également développé au début d’une expression d’affectation de variable shell comme DIRNAME=~/anaconda2 ; bien que le tilde de votre question suive également un signe égal, cet usage n'a pas de signification particulière pour le shell (il s'agit simplement d'un élément transmis à un programme) et ne déclenche pas d'expansion.

    
réponse donnée alexis 07.03.2017 - 11:12
la source
31

Développement de tilde en python

La réponse est courte & simple:

python ne développe pas ~ sauf si vous utilisez:

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

Voir aussi ici :

os.path.expanduser(path)
On Unix and Windows, return the argument with an initial component of ~ or ~user replaced by that user‘s home directory.

On Unix, an initial ~ is replaced by the environment variable HOME if it is set; otherwise the current user’s home directory is looked up in the password directory through the built-in module pwd. An initial ~user is looked up directly in the password directory.

    
réponse donnée Jacob Vlijm 07.03.2017 - 09:19
la source
12

Les extensions de tilde ne sont effectuées que dans quelques contextes légèrement différents d'un shell .

Alors qu'il est exécuté dans:

var=~

Ou

export var=~

dans quelques coquilles. Ce n'est pas dans

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

dans les shells POSIX.

Il est dans bash bien que lorsqu'il n'est pas en mode de conformité POSIX (comme lorsqu'il était appelé sh ou lorsque POSIXLY_CORRECT est dans l'environnement):

$ 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=~

Cependant, c’est uniquement lorsque la partie gauche de = a la forme d’un nom de variable valide non entre guillemets. Ainsi, même si elle serait développée dans cmd prefix=~ , elle ne serait pas dans cmd --prefix=~ (car --prefix est nom de variable non valide), ni dans cmd "p"refix=~ (à cause de cette citation, p ) ni dans var=prefix; cmd $var=~ .

Dans zsh , vous pouvez définir l'option magic_equal_subst pour que ~ soit étendu après tout = non cité.

$ 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

Dans le cas de ~ (par opposition à ~user ), vous pouvez simplement utiliser $HOME à la place:

cmd --whatever="$HOME/whatever"

~ se développe à la valeur de $HOME . Si $HOME n'est pas défini, le comportement varie d'un shell à l'autre. Certains shells interrogent la base de données utilisateur. Si vous voulez en tenir compte, vous pouvez le faire (et c'est aussi ce que vous devez faire pour ~user ):

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

Dans tous les cas, dans les shells autres que zsh , souvenez-vous que vous devez citer des extensions variables!

    
réponse donnée Stéphane Chazelas 07.03.2017 - 12:03
la source
6

~ a des règles de développement particulières, auxquelles votre commande ne satisfait pas. Spécifiquement, il est développé uniquement lorsqu'il est non mis entre guillemets, soit au début d'un mot (par exemple python ~/script.py ), soit au début d'une affectation de variable (par exemple PYTHONPATH=~/scripts python script.py ). Ce que vous avez, c'est --data_path=~/blabla , qui est un mot unique en termes de shell. Par conséquent, aucune extension n'est effectuée.

Une solution immédiate consiste à utiliser la variable shell $HOME , qui suit les règles habituelles de développement des variables:

python ptb_word_lm.py --data_path=$HOME/blabla
    
réponse donnée Dmitry Grigoryev 07.03.2017 - 11:28
la source

Lire d'autres questions sur les étiquettes