私はMacOSXでシェルとしてbash
を使用しています。次のように作成されたシンボリックリンクがあります。
ln -s /usr/bin/python python2
私はpython2を使用するパッケージを持っています。現在の作業ディレクトリに/usr/bin/python
へのシンボルリンクを作成します。これは実際にはpython2です。コマンドラインからpython2
を実行すると、次のエラーが発生します。
python2: realpath couldn't resolve "/usr/bin/python2"
ただし、このように呼び出すと、./python2
によってパスが正しく解決されます。私のPATH
には.
が含まれています。実際、テストのために.
のみが含まれるように変更しました。
どうすれば解決できますか?ありがとう!
以下の提案された解決策の多くは、私にはうまくいきません。人々がテキストの海で溺れることのないように、できるだけ焦点を絞って簡潔な質問を抽出しようとしましたが、明らかに背景をもっと提供する必要があります。
私はgitからクローンしたパッケージで開発しようとしています。元のパッケージgit-multimail
は、Linuxの一部のバリアントで開発されました(私はUbuntuと推測しています)。 できるだけ変更せずにMacOSXでそれとそのテストスイートを使用できるように変更しようとしています。提案されたソリューションのいくつかが理想的でない理由は次のとおりです。
rootとして、/ usr/bin /にpython2
シンボリックリンクを作成します。これを必要としないソリューションを探しています。これは最初は明らかなオプションでしたが、ホストシステムをできるだけ変更しないソリューションが欲しいです。これが、現在の作業ディレクトリに一時的なシンボリックリンクを作成し、CWD(つまり.
)をパスに追加し、終了時にこれを破棄したい(つまり、シンボリックリンク)理由です。
pythonスクリプトを既存のpythonで呼び出すラッパースクリプトを作成します。これに関する問題は、テストスイートの多くが実際のscript_filesを実行可能ファイルとして使用することです。正しい実行環境を見つけるためのシバン。これは、テストスイートを大幅に編集することを意味します。このコンテキスト(テストフレームワークのスニペットについては以下を参照)では、すべての.py
ファイルにラッパーを追加する必要があります。さらに、ユーザー/開発者は、使用しているシステムに応じてパッケージを使用するためのさまざまなルールに注意する必要があります(つまり、MacOSXでは、pythonファイルを呼び出さずに使用しないでください)ラッパー経由または明示的に/usr/bin/python file.py
)を呼び出します。
#! /bin/sh
D=$(cd $(dirname "$0") && pwd)
MULTIMAIL="$D/../git-multimail/git_multimail.py"
POST_RECEIVE="$D/../git-multimail/post-receive"
TESTREPO=$("$D/create-test-repo")
HOME="$D"
XDG_CONFIG_HOME="$D"
GIT_CONFIG_NOSYSTEM=1
export HOME XDG_CONFIG_HOME GIT_CONFIG_NOSYSTEM
cd $TESTREPO
test_email() {
REFNAME="$1"
OLDREV="$2"
NEWREV="$3"
echo "$OLDREV" "$NEWREV" "$REFNAME" | USER=pushuser "$MULTIMAIL"
}
python
へのすべてのpython2
参照の変更 READMEはこれを示唆していますが、システムが変更を認識しているため、バージョン管理は事実上役に立たなくなります新しいバージョンとして、実際には(意味的に)ない場合。
私は(3)を使用していますが、より良い解決策を見つけようとしています。私はこれが正しい方法であることを受け入れます(つまり、「python2」を/usr/bin/python
にポイントする適切な方法はありません。これは、テストスイートと実際のフレームワークに多くの変更を加えることなく、移植可能で目立たないものです) 。
シンボリックリンクを解決(または調査)する必要がある場合は、プラットフォームに依存しないbashライブラリ 'realpath-lib'を使用できます。デフォルトでは、readlinkをエミュレートし、MacまたはUnixで動作します。 Github または Bitbucket にあり、無料です。
しかし、ローカル(作業)ディレクトリーから(./python2ではなく)python2を実行したいようです。 .bashrcのエイリアスを使用してこれを実行できる場合があります。そうでない場合は、PATH環境変数に作業ディレクトリ(シンボリックリンクを含む)を追加する必要があります。これは、現在のセッションのみ、または.bashrcファイル内で行うこともできます。これは、特定のユーザーのためのソリューションである可能性があります。
すべてのユーザーに対して機能する別のオプションは、/ usr/bin/pythonへのpython2シンボリックリンクをパスの別のディレクトリ、たとえば/ usr/local/binに作成することです。おそらく次のようなものです:
Sudo ln -s /usr/bin/python /usr/local/bin/python2
次に、すべてのユーザーまたはスクリプトがpythonまたはpython2コマンドを見つけます。もちろん、このオプションをインストールするには、管理者(root)権限が必要です。
同じプログラムの複数のバージョンを管理し、切り替えるためにAppleのシステムを危険にさらしていると思います。 python2
という名前の次のスクリプトを使用すると、エレガントではありませんが問題なく目的の機能を実行できます。
#!/bin/bash
exec /usr/bin/python "$@"
それを実行可能(chmod +x python2
)にすると、あなたは仕事に取り掛かります。
/usr/bin/python
を実行すると、同じディレクトリでpython2.7
を見つけて実行します。シンボリックリンクは、システムが/usr/bin
へのシンボリックリンクをたどるので失敗し、が見つかりませんpython2
があります。シンボリックリンクの代わりに「ハードリンク」を使用すると、さらに一歩先を行くことができます。
rm python2
ln /usr/bin/python python2
今、従うべきシンボリックリンクはなく、同じファイル(inode)に対する2つのファイル名だけです。しかし今、私は次のメッセージで失敗します:
python2: posix_spawn: /Users/alexis/.../python22.7: No such file or directory
python22.7
に注意してください:フレームワークは、作成した名前に2.7
を追加しています!これを解明し、その期待に一致するリンクのフォレストをセットアップする代わりに、バージョン管理フレームワークの邪魔にならないように滞在し、上記の解決策を使用することをお勧めします。
PS。より良い解決策があるかもしれません:あなたが最初に何をする必要があるかを説明するなら(なぜpython2
をpython
のエイリアスとして提供する必要があるのですか)、誰かがおそらく別の方法であなたを助けることができます。これは、stackexchange言語では「XY問題」として知られています...
試してください:
ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
@alexisの回答に関連して、_/usr/bin
_のpythonバージョンは実際のpythonではありません。
これは、次の3つの方法で明らかになります。
発生しているエラーは、pythonが通常生成するエラーではありません。 pythonの動作は、別のpythonを探すことではなく、pythonスクリプトを実行することです。
_/usr/bin/python
_のシャサムと実際に実行されるpython2.7を計算する場合:
_shasum /usr/bin/python
3782d9ab14b35037c9c7fb665439a5fa695c54a6 /usr/bin/python
_
_shasum /usr/bin/python2.7
476fa96c80ac26a85b2d3b01ddfd19e513660c2c /usr/bin/python2.7
_
それらは完全に異なります。さらに、ファイルサイズは〜20kバイト異なります。
_ll /usr/bin/python
-rwxr-xr-x 1 root wheel 66880 May 17 2019 /usr/bin/python
_
vs.
_ll /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
-rwxr-xr-x 1 root wheel 43104 May 17 2019 /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
_
したがって、(エラーが示すように)_/usr/bin/python
_は向きを変えて_/usr/bin/python2.7
_を探します。
_ll /usr/bin/python2.7
lrwxr-xr-x 1 root wheel 75 Jul 1 2019 /usr/bin/python2.7 -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
_
これが、以下が機能する理由です(礼儀@ liangmin-liの回答):
_ ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
_
Unixコマンドreadlink
を使用して、リンクの物理パスを見つけることができます。
次のリンクがあるとします。
$ ls -l /usr/bin/etags
lrwxrwxrwx. 1 root root 29 Dec 10 22:56 /usr/bin/etags -> /etc/alternatives/emacs.etags
$ ls -l /etc/alternatives/emacs.etags
lrwxrwxrwx. 1 root root 20 Dec 10 22:56 /etc/alternatives/emacs.etags -> /usr/bin/etags.ctags
$ ls -l /usr/bin/etags.ctags
lrwxrwxrwx. 1 root root 5 Dec 10 22:56 /usr/bin/etags.ctags -> ctags
シンボリックリンクが指す値を見つけるには
$ readlink /usr/bin/etags
/etc/alternatives/emacs.etags
注:上記の結果は別のリンクである可能性があります。これを解決するには、以下の#2を参照してください。
シンボリックリンクが指す値の絶対パスを見つけるには
$ readlink -f /usr/bin/etags
/usr/bin/ctags
わかりません。ラッパーlinkは問題ないが、ラッパーscriptは問題ないと思いますか?どちらも単なる間接参照のレベルです。また、特定のディレクトリからのみ呼び出すようにユーザーに指示する必要はありませんか?
いずれの場合でも、$PATH
で現在の作業ディレクトリを取得できます。
echo "echo \"Hi! I'm python\"" >|./python
chmod +x ./python
PATH="${PWD}:${PATH}"
python
#OUTPUT#
Hi! I'm python
rm python
python -V
ln -s /usr/bin/python2 ./python
python -V
#OUTPUT#
Python 3.4.0
Python 2.7.6
PATH="${PATH#"${PWD}:"}"
python -V
#OUTPUT#
Python 3.4.0
入手してください。あなたの$PATH
のうち。それは恐ろしい考えです。