目次: Python
Pythonの仮想環境(venv)は便利ですが、移動したりリネームすると使えなくなる罠があります。変な仕様ですね。
使えなくなる理由はいくつかありますが、そのうちの1つはvenv/binの下にあるPythonスクリプトのshebangにPythonインタプリターの絶対パスが書かれているからです。なぜこんなことになるのかインストーラ(pip)の実装を軽く調べました。
調べ方もメモしておきます。実験用のvenv環境を作成します。
$ python -m venv venv $ source venv/bin/activate
実験するときはwheelパッケージをinstall/uninstallするのが動作も速いしやりやすいです。wheelでなくともbinの下に実行ファイルをインストールするパッケージであれば何でも良いです。ただし例えばsimplejsonパッケージはbinの下に何もインストールしないので今回の調査には適しません。
(venv) $ pip install wheel (venv) $ pip uninstall -y wheel
あとはpipパッケージのスクリプトにprint文を入れつつinstall/uninstallを繰り返し、スクリプトのどこで何をしているか調べるだけです。
Pythonスクリプトのshebangに絶対パスを書く処理は、pipの下記の部分です。
# venv/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py
def _make_script(self, entry, filenames, options=None):
post_interp = b''
if options:
args = options.get('interpreter_args', [])
if args:
args = ' %s' % ' '.join(args)
post_interp = args.encode('utf-8')
shebang = self._get_shebang('utf-8', post_interp, options=options) #★★shebangを得る★★
script = self._get_script_text(entry).encode('utf-8')
scriptnames = self.get_script_filenames(entry.name)
if options and options.get('gui', False):
ext = 'pyw'
else:
ext = 'py'
self._write_script(scriptnames, shebang, script, filenames, ext) #★★スクリプトをファイルに書き込む★★
...
def _get_shebang(self, encoding, post_interp=b'', options=None):
enquote = True
if self.executable:
executable = self.executable
enquote = False # assume this will be taken care of
elif not sysconfig.is_python_build():
executable = get_executable() #★★インタプリタ実行パスを得る★★
elif in_venv(): # pragma: no cover
executable = os.path.join(sysconfig.get_path('scripts'), 'python%s' % sysconfig.get_config_var('EXE'))
else: # pragma: no cover
if os.name == 'nt':
# for Python builds from source on Windows, no Python executables with
# a version suffix are created, so we use python.exe
executable = os.path.join(sysconfig.get_config_var('BINDIR'),
'python%s' % (sysconfig.get_config_var('EXE')))
else:
executable = os.path.join(
sysconfig.get_config_var('BINDIR'),
'python%s%s' % (sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('EXE')))
...
# venv/lib/python3.12/site-packages/pip/_vendor/distlib/util.py
def get_executable():
# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as
# changes to the stub launcher mean that sys.executable always points
# to the stub on OS X
# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__'
# in os.environ):
# result = os.environ['__PYVENV_LAUNCHER__']
# else:
# result = sys.executable
# return result
# Avoid normcasing: see issue #143
# result = os.path.normcase(sys.executable)
result = sys.executable #★★実行中のpythonインタープリタの絶対パスを得る★★
if not isinstance(result, text_type):
result = fsdecode(result)
return result
コメントに書いた通り、実行中のPythonインタープリタの絶対パスsys.executableからshebangを生成します。この処理はvenv/bin以下にインストールされるPythonスクリプト全てに適用され、venv/bin以下のスクリプト全てにPythonの絶対パスが書かれるようです。
この記事にコメントする
| < | 2025 | > | ||||
| << | < | 01 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | - |
25年10月6日
25年10月6日
25年9月29日
25年9月29日
20年8月24日
20年8月24日
16年2月14日
16年2月14日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
25年7月20日
20年8月16日
20年8月16日
20年8月16日
20年8月16日
24年6月17日
24年6月17日
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: