Ist es möglich, alle Python-Pakete gleichzeitig mit pip
zu aktualisieren?
Beachten Sie, dass auf dem offiziellen Issue-Tracker eine Funktionsanforderung vorhanden ist.
Es gibt noch keine integrierte Flagge, die Sie jedoch verwenden können
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
Hinweis: Hier gibt es unendlich viele Variationsmöglichkeiten. Ich versuche, diese Antwort kurz und einfach zu halten, aber schlagen Sie bitte Variationen in den Kommentaren vor!
In älteren Versionen von pip
können Sie stattdessen Folgendes verwenden:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
Mit grep
können editierbare Paketdefinitionen ("-e") übersprungen werden, wie von @jawache vorgeschlagen. (Ja, Sie können grep
+ cut
durch sed
oder awk
oder Perl
oder ...) ersetzen.
Das -n1
-Flag für xargs
verhindert das Stoppen von alles, wenn das Aktualisieren eines Pakets fehlschlägt (danke @andsens ).
Sie können den folgenden Python-Code verwenden. Im Gegensatz zu pip freeze
werden hier keine Warnungen und FIXME-Fehler ausgegeben . Für pip <10.0.1
import pip
from subprocess import call
packages = [dist.project_name for dist in pip.get_installed_distributions()]
call("pip install --upgrade " + ' '.join(packages), Shell=True)
Für pip> = 10.0.1
import pkg_resources
from subprocess import call
packages = [dist.project_name for dist in pkg_resources.working_set]
call("pip install --upgrade " + ' '.join(packages), Shell=True)
Um alle lokalen Pakete zu aktualisieren; Sie könnten pip-review
verwenden:
$ pip install pip-review
$ pip-review --local --interactive
pip-review
ist eine Abzweigung von pip-tools
. Siehe pip-tools
issue erwähnt von @knedlsepp . pip-review
-Paket funktioniert, aber pip-tools
-Paket funktioniert nicht mehr.
pip-review
funktioniert unter Windows seit Version 0.5 .
Funktioniert unter Windows. Sollte für andere auch gut sein . ($ Ist das Verzeichnis, in dem Sie sich befinden, in Eingabeaufforderung, z. B. C:/Users/Username>)
tun
$ pip freeze > requirements.txt
Öffnen Sie die Textdatei, ersetzen Sie == durch> =
dann mach
$ pip install -r requirements.txt --upgrade
Wenn Sie ein Problem mit einem bestimmten Paket haben, das das Upgrade zum Stillstand gebracht hat (manchmal numpy), gehen Sie einfach in das Verzeichnis ($), kommentieren Sie den Namen aus (fügen Sie ein # voran) und führen Sie das Upgrade erneut aus. Sie können diesen Abschnitt später rückgängig machen. Dies eignet sich auch zum Kopieren von globalen Python-Umgebungen.
Ich mag auch die Pip-Review-Methode:
py2
$ pip install pip-review
$ pip-review --local --interactive
py3
$ pip3 install pip-review
$ py -3 -m pip_review --local --interactive
Sie können 'a' auswählen, um alle Pakete zu aktualisieren. Wenn ein Upgrade fehlschlägt, führen Sie es erneut aus und das nächste wird fortgesetzt.
Windows-Version nach Rücksprache mit documentation für FOR
von Rob van der Woude
for /F "delims===" %i in ('pip freeze -l') do pip install -U %i
Sie können nur die Pakete ausdrucken, die veraltet sind
pip freeze | cut -d = -f 1 | xargs -n 1 pip search | grep -B2 'LATEST:'
Die folgenden Einzeiler könnten sich als hilfreich erweisen:
pip list --format freeze --outdated | sed 's/(.*//g' | xargs -n1 pip install -U
xargs -n1
läuft weiter, wenn ein Fehler auftritt.
Wenn Sie mehr Kontrolle über das, was weggelassen wird und was einen Fehler auslöst, benötigen, sollten Sie das Flag -n1
nicht hinzufügen und die zu ignorierenden Fehler explizit definieren, indem Sie für jeden einzelnen Fehler die folgende Zeile "piping":
| sed 's/^<First characters of the error>.*//'
Hier ist ein Arbeitsbeispiel:
pip list --format freeze --outdated | sed 's/(.*//g' | sed 's/^<First characters of the first error>.*//' | sed 's/^<First characters of the second error>.*//' | xargs pip install -U
Diese Option erscheint mir einfacher und lesbarer:
pip install -U `pip list --outdated | tail -n +3 | awk '{print $1}'`
Die Erklärung ist, dass pip list --outdated
eine Liste aller veralteten Pakete in diesem Format ausgibt:
Package Version Latest Type
--------- ------- ------ -----
fonttools 3.31.0 3.32.0 wheel
urllib3 1.24 1.24.1 wheel
requests 2.20.0 2.20.1 wheel
tail -n +3
überspringt die ersten beiden Zeilen und awk '{print $1}'
wählt das erste Wort jeder Zeile aus.
Dies scheint prägnanter zu sein.
pip list --outdated | cut -d ' ' -f1 | xargs -n1 pip install -U
Erläuterung:
pip list --outdated
bekommt solche Zeilen
urllib3 (1.7.1) - Latest: 1.15.1 [wheel]
wheel (0.24.0) - Latest: 0.29.0 [wheel]
In cut -d ' ' -f1
setzt -d ' '
"Leerzeichen" als Trennzeichen, -f1
bedeutet, die erste Spalte abzurufen.
Die obigen Zeilen werden also:
urllib3
wheel
Übergeben Sie sie dann an xargs
, um den Befehl pip install -U
mit jeder Zeile als anhängende Argumente auszuführen
-n1
begrenzt die Anzahl der an jeden Befehl pip install -U
übergebenen Argumente auf 1
Robustere Lösung
Verwenden Sie für pip3 folgendes:
pip3 freeze --local |sed -rn 's/^([^=# \t\\][^ \t=]*)=.*/echo; echo Processing \1 ...; pip3 install -U \1/p' |sh
Für Pip entfernen Sie einfach die 3er als solche:
pip freeze --local |sed -rn 's/^([^=# \t\\][^ \t=]*)=.*/echo; echo Processing \1 ...; pip install -U \1/p' |sh
OSX Oddity
OSX wird ab Juli 2017 mit einer sehr alten Version von Sed (ein Dutzend Jahre) ausgeliefert. Um erweiterte reguläre Ausdrücke zu erhalten, verwenden Sie in der obigen Lösung -E anstelle von -r.
Probleme mit gängigen Lösungen lösen
Diese Lösung ist gut entwickelt und getestet1Allerdings gibt es auch bei den gängigsten Lösungen Probleme.
Der obige Befehl verwendet die einfachste und meist tragbare Pip-Syntax in Kombination mit sed und sh, um diese Probleme vollständig zu lösen. Details der sed-Operation können mit der kommentierten Version überprüft werden2.
Einzelheiten
[1] In einem Linux-Cluster 4.8.16-200.fc24.x86_64 getestet und regelmäßig verwendet und mit fünf anderen Linux/Unix-Varianten getestet. Es läuft auch auf Cygwin64, das unter Windows 10 installiert ist. Tests unter iOS sind erforderlich.
[2] Um die Anatomie des Befehls besser zu sehen, entspricht dies genau dem obigen Befehl pip3 mit Kommentaren:
# match lines from pip's local package list output
# that meet the following three criteria and pass the
# package name to the replacement string in group 1.
# (a) Do not start with invalid characters
# (b) Follow the rule of no white space in the package names
# (c) Immediately follow the package name with an equal sign
sed="s/^([^=# \t\\][^ \t=]*)=.*"
# separate the output of package upgrades with a blank line
sed="$sed/echo"
# indicate what package is being processed
sed="$sed; echo Processing \1 ..."
# perform the upgrade using just the valid package name
sed="$sed; pip3 install -U \1"
# output the commands
sed="$sed/p"
# stream edit the list as above
# and pass the commands to a Shell
pip3 freeze --local |sed -rn "$sed" |sh
[3] Das Aktualisieren einer Python- oder PIP-Komponente, die auch beim Upgrade einer Python- oder PIP-Komponente verwendet wird, kann eine potenzielle Ursache für einen Deadlock oder eine Paketdatenbank sein.
Ich hatte das gleiche Problem mit dem Upgrade. Ich aktualisiere nie alle Pakete. Ich aktualisiere nur das, was ich brauche, weil das Projekt möglicherweise kaputt geht.
Da es keine einfache Möglichkeit gab, Paket für Paket zu aktualisieren und die Datei Requirements.txt zu aktualisieren, habe ich Folgendes geschrieben: pip-upgrader welches auch die Versionen Ihrer requirements.txt
-Datei für die Pakete aktualisiert ausgewählt (oder alle Pakete).
Installation
pip install pip-upgrader
Verwendungszweck
Aktivieren Sie Ihre Virtualenv (wichtig, da dadurch auch die neuen Versionen der aktualisierten Pakete in der aktuellen Virtualenv installiert werden).
cd
in Ihr Projektverzeichnis, und führen Sie dann Folgendes aus:
pip-upgrade
Erweiterte Verwendung
Wenn die Anforderungen an einem nicht standardmäßigen Speicherort abgelegt werden, senden Sie sie als Argumente:
pip-upgrade path/to/requirements.txt
Wenn Sie bereits wissen, welches Paket Sie aktualisieren möchten, senden Sie es einfach als Argumente:
pip-upgrade -p Django -p celery -p dateutil
Wenn Sie ein Upgrade auf die Vor-Release-/Post-Release-Version durchführen müssen, fügen Sie Ihrem Befehl das Argument --prerelease
hinzu.
Vollständige Offenlegung: Ich habe dieses Paket geschrieben.
Von https://github.com/cakebread/yolk :
$ pip install -U `yolk -U | awk '{print $1}' | uniq`
sie müssen jedoch zuerst Eigelb bekommen:
$ Sudo pip install -U yolk
Einzeiler-Version von @ Ramanas Antwort .
python -c 'import pip, subprocess; [subprocess.call("pip install -U " + d.project_name, Shell=1) for d in pip.get_installed_distributions()]'
`
wenn Sie eine virtualenv verwenden und nur Pakete added zu Ihrer virtualenv aktualisieren möchten, können Sie Folgendes tun:
pip install `pip freeze -l | cut --fields=1 -d = -` --upgrade
$ pip install pipupgrade
$ pipupgrade --latest --yes
pipupgrade hilft Ihnen beim Upgrade Ihres Systems, lokalen Pakets oder Paketen von einer requirements.txt
-Datei! Es aktualisiert auch selektiv Pakete, die die Änderungen nicht beschädigen. Kompatibel mit Python2.7 +, Python3.4 + und pip9 +, pip10 +, pip18 +.
HINWEIS: Ich bin der Autor des Tools.
Windows PowerShell-Lösung
pip freeze | %{$_.split('==')[0]} | %{pip install --upgrade $_}
Die einfachste und schnellste Lösung, die ich in der Diskussion " pip" gefunden habe ist:
Sudo -H pip install pipdate
Sudo -H pipdate
Sie können dies versuchen:
for i in ` pip list|awk -F ' ' '{print $1}'`;do pip install --upgrade $i;done
Das ziemlich erstaunliche Eigelb macht dies einfach.
pip install yolk3k # don't install `yolk`, see https://github.com/cakebread/yolk/issues/35
yolk --upgrade
Weitere Informationen zu Yolk: https://pypi.python.org/pypi/yolk/0.4.3
Es kann viele Dinge tun, die Sie wahrscheinlich nützlich finden.
@ Ramanas Antwort arbeitete am besten für mich, aber ich musste ein paar Fänge hinzufügen:
import pip
for dist in pip.get_installed_distributions():
if 'site-packages' in dist.location:
try:
pip.call_subprocess(['pip', 'install', '-U', dist.key])
except Exception, exc:
print exc
Die site-packages
-Prüfung schließt meine Entwicklungspakete aus, da sich diese nicht im Verzeichnis der Site-Packages des Systems befinden. Der try-except überspringt einfach Pakete, die aus PyPI entfernt wurden.
@endolith: Ich habe auch auf eine einfache pip.install(dist.key, upgrade=True)
gehofft, aber es sieht nicht so aus, als würde pip von etwas anderem als der Befehlszeile verwendet werden (die Docs erwähnen nicht die interne API und die Pip-Entwickler nicht docstrings verwenden).
Gesendet durch eine Pull-Anfrage an das Pip Folk ; Verwenden Sie in der Zwischenzeit diese Pip Library-Lösung, die ich geschrieben habe:
from pip import get_installed_distributions
from pip.commands import install
install_cmd = install.InstallCommand()
options, args = install_cmd.parse_args([package.project_name
for package in
get_installed_distributions()])
options.upgrade = True
install_cmd.run(options, args) # Chuck this in a try/except and print as wanted
Das schien für mich zu funktionieren ...
pip install -U $(pip list --outdated|awk '{printf $1" "}')
Ich verwendete printf
mit einem Leerzeichen, um die Paketnamen richtig zu trennen.
awk-Aktualisierungspakete verwenden:
pip install -U $(pip freeze | awk -F'[=]' '{print $1}')
windows-Powershell-Update
foreach($p in $(pip freeze)){ pip install -U $p.Split("=")[0]}
Mein Skript:
pip list --outdated --format=legacy | cut -d ' ' -f1 | xargs -n1 pip install --upgrade
Der kürzeste und einfachste unter Windows.
pip freeze > requirements.txt && pip install --upgrade -r requirements.txt && rm requirements.txt
Ist das nicht effektiver?
pip3 list -o | grep -v -i warning | cut -f1 -d' ' | tr " " "\n" | awk '{if(NR>=3)print}' | cut -d' ' -f1 | xargs -n1 pip3 install -U
pip list -o
listet veraltete Pakete auf;grep -v -i warning
invertierte Übereinstimmung mit warning
, um Fehler beim Aktualisieren zu vermeidencut -f1 -d1' '
gibt das erste Word zurück - den Namen des veralteten Pakets;tr "\n|\r" " "
konvertiert das mehrzeilige Ergebnis von cut
in eine einzeilige, durch Leerzeichen getrennte Liste.awk '{if(NR>=3)print}'
überspringt Headerzeilen cut -d' ' -f1
ruft die erste Spalte abxargs -n1 pip install -U
nimmt 1 Argument aus der Pipe links davon und übergibt es an den Befehl, um die Liste der Pakete zu aktualisieren.Der pip_upgrade_outdated
erledigt den Job. Nach seinen Dokumenten :
usage: pip_upgrade_outdated [-h] [-3 | -2 | --pip_cmd PIP_CMD]
[--serial | --parallel] [--dry_run] [--verbose]
[--version]
Upgrade outdated python packages with pip.
optional arguments:
-h, --help show this help message and exit
-3 use pip3
-2 use pip2
--pip_cmd PIP_CMD use PIP_CMD (default pip)
--serial, -s upgrade in serial (default)
--parallel, -p upgrade in parallel
--dry_run, -n get list, but don't upgrade
--verbose, -v may be specified multiple times
--version show program's version number and exit
Schritt 1:
pip install pip-upgrade-outdated
Schritt 2:
pip_upgrade_outdated
import pip
pkgs = [p.key for p in pip.get_installed_distributions()]
for pkg in pkgs:
pip.main(['install', '--upgrade', pkg])
oder auch:
import pip
commands = ['install', '--upgrade']
pkgs = commands.extend([p.key for p in pip.get_installed_distributions()])
pip.main(commands)
Funktioniert schnell, da nicht ständig eine Shell gestartet wird. Ich würde gerne die Zeit dafür finden, diese Liste mit der veralteten Liste noch schneller zu machen.
eine Zeile in Powershell 5.1 mit Adm-Rechten, Python 3.6.5 und Pip Version 10.0.1:
pip list -o --format json | ConvertFrom-Json | foreach {pip install $_.name -U --no-warn-script-location}
es funktioniert reibungslos, wenn in der liste keine zerbrochenen pakete oder sonderräder sind ...
Wie wäre es mit:
pip install -r <(pip freeze) --upgrade
Ich habe den Code von Ramana ausprobiert und habe unter Ubuntu herausgefunden, dass Sie für jeden Befehl Sudo
schreiben müssen. Hier ist mein Skript, das auf Ubuntu 13.10 gut funktioniert:
#!/usr/bin/env python
import pip
from subprocess import call
for dist in pip.get_installed_distributions():
call("Sudo pip install --upgrade " + dist.project_name, Shell=True)
Ich habe in letzter Zeit pur verwendet. Es ist einfach und auf den Punkt. Es aktualisiert Ihre requirements.txt
-Datei, um die Aktualisierungen wiederzugeben. Sie können dann wie üblich ein Upgrade mit Ihrer requirements.txt
-Datei durchführen.
$ pip install pur
...
Successfully installed pur-4.0.1
$ pur
Updated boto3: 1.4.2 -> 1.4.4
Updated Django: 1.10.4 -> 1.10.5
Updated Django-bootstrap3: 7.1.0 -> 8.1.0
All requirements up-to-date.
$ pip install --upgrade -r requirements.txt
Successfully installed Django-1.10.5 ...
Hier ist ein Skript, das nur die veralteten Pakete aktualisiert.
import os, sys
from subprocess import check_output, call
file = check_output(["pip.exe", "list", "--outdated", "--format=legacy"])
line = str(file).split()
for distro in line[::6]:
call("pip install --upgrade " + distro, Shell=True)
Für eine neue Version, die nicht als Legacy-Format (Version 18+) ausgegeben wird.
import os, sys
from subprocess import check_output, call
file = check_output(["pip.exe", "list", "-o", "--format=json"])
line = str(file).split()
for distro in line[1::8]:
distro = str(distro).strip('"\",')
call("pip install --upgrade " + distro, Shell=True)
Alle veralteten Pakete anzeigen
pip list --outdated --format=columns
Installieren
Sudo pip install pipdate
dann tippen
Sudo -H pipdate
Hier ist meine Variante der Antwort von rbp, die "editierbare" und Entwicklungsverteilungen umgeht. Es hat zwei Schwachstellen des Originals: Es wird erneut heruntergeladen und unnötig neu installiert; Ein Fehler bei einem Paket verhindert danach das Upgrade jedes Pakets.
pip freeze |sed -ne 's/==.*//p' |xargs pip install -U --
Verwandte Fehlerberichte, etwas unzusammenhängend nach der Migration von Bitbucket:
dies ist eine andere Möglichkeit, ein Skript in Python auszuführen
import pip, tempfile, contextlib
with tempfile.TemporaryFile('w+') as temp:
with contextlib.redirect_stdout(temp):
pip.main(['list','-o'])
temp.seek(0)
for line in temp:
pk = line.split()[0]
print('--> updating',pk,'<--')
pip.main(['install','-U',pk])
Dies ist eine PowerShell-Lösung für Python 3:
pip3 list --outdated --format=legacy | ForEach { pip3 install -U $_.split(" ")[0] }
Und für Python 2:
pip2 list --outdated --format=legacy | ForEach { pip2 install -U $_.split(" ")[0] }
Dadurch werden die Pakete nacheinander aktualisiert. So ein
pip3 check
pip2 check
danach sollte sichergestellt werden, dass keine Abhängigkeiten gebrochen werden.
Eine Zeile in cmd:
for /F "delims= " %i in ('pip list --outdated --format=legacy') do pip install -U %i
So ein
pip check
danach sollte sichergestellt werden, dass keine Abhängigkeiten gebrochen werden.
Und noch ein anderer Weg: for pkg in $(pip list | cut -d' ' -f1); do Sudo pip install --upgrade $pkg; done
import os
import pip
from subprocess import call, check_call
pip_check_list = ['pip', 'pip3']
pip_list = []
FNULL = open(os.devnull, 'w')
for s_pip in pip_check_list:
try:
check_call([s_pip, '-h'], stdout=FNULL)
pip_list.append(s_pip)
except FileNotFoundError:
pass
for dist in pip.get_installed_distributions():
for pip in pip_list:
call("{0} install --upgrade ".format(pip) + dist.project_name, Shell=True)
Ich nahm @ Ramanas Antwort und machte es pip3 freundlich.
Als eine andere Antwort hier heißt es:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
Ist eine mögliche Lösung, Bei einigen Kommentaren, darunter auch ich, gab es bei der Verwendung dieses Befehls Probleme mit Berechtigungen. Eine kleine Änderung zu Folgendem löste die für mich.
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 Sudo -H pip install -U
Beachten Sie das hinzugefügte Sudo -H, das es dem Befehl erlaubte, mit Root-Berechtigungen rumzusteigen.
Hier ist meine Variation:
pip list --outdated --format=legacy | awk '{print $1;}' | xargs -n1 pip install -U
pip list -o | cut -d' ' -f1 | xargs -n1 pip install -U 2> /dev/null
wenn Sie zwei verschiedene Python-Versionen haben und nur das gesamte Paket von Python3 aktualisieren möchten, geben Sie einfach pip3
anstelle von pip
ein.
Der 2> /dev/null
dient dazu, alle ärgerlichen Fehlermeldungen zu beseitigen
Die kürzeste und einfachste, die ich finden kann:
pip install -U $(pip freeze | cut -d"=" -f1)
Mit der Taste $(cmd)
können Sie eine beliebige Shell-Befehlszeile umbrechen (gibt ihre Ausgabe zurück).
Pure bash/zsh oneliner, um das zu tun:
for p in $(pip list -o --format freeze); do pip install -U ${p%%=*}; done
Oder in Nizza-formatierter Form:
for p in $(pip list -o --format freeze)
do
pip install -U ${p%%=*}
done
Eine schnelle Möglichkeit, alle installierten Pakete zu aktualisieren, könnte folgende sein:
for pkg in $(pip list | cut -d' ' -f1) ; do pip install $pkg -U ; done
python -c 'import pip; [pip.main(["install", "--upgrade", d.project_name]) for d in pip.get_installed_distributions()]'
Einzeiler!
Wenn Sie möchten, dass das Upgrade nur gepackt von pip installiert wird, und um das Upgrade von Paketen zu vermeiden, die von anderen Tools (wie apt, yum usw.) installiert werden, können Sie dieses Skript verwenden, das ich unter Ubuntu verwende. - basierend auf diesem Beitrag :
printf "To update with pip: pip install -U"
pip list --outdated 2>/dev/null | gawk '{print $1;}' | while read; do pip show "${REPLY}" 2>/dev/null | grep 'Location: /usr/local/lib/python2.7/dist-packages' >/dev/null; if (( $? == 0 )); then printf " ${REPLY}"; fi; done; echo
installiere zuerst jq (mac):
$ brew install jq
2.
$pip3 install --upgrade `pip3 list --outdated --format json | jq '.[] | .name' | awk -F'"' '{print $2}'`
Fügen Sie einfach eine JSON + JQ-Antwort für Datensätze hinzu:
pip list -o --format json | jq '.[] | .name' | xargs pip install -U
die beste Lösung, die auch in conda env funktioniert, ist:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 |cut -d ':' -f 2 | xargs -n1 pip install -U
Das folgende cmd
Snippet bewirkt Folgendes:
- Upgrades
pip
auf die neueste Version.- Aktualisiert alle veralteten Pakete.
- Überprüfen Sie für jedes Paket, für das ein Upgrade durchgeführt wird,
requirements.txt
auf Versionsspezifizierer.
@echo off
Setlocal EnableDelayedExpansion
rem https://stackoverflow.com/questions/2720014
echo Upgrading pip...
python -m pip install --upgrade pip
echo.
echo Upgrading packages...
set upgrade_count=0
pip list --outdated > pip-upgrade-outdated.txt
for /F "skip=2 delims= " %%i in (pip-upgrade-outdated.txt) do (
echo ^>%%i
set package=%%i
set requirements=!package!
rem for each outdated package check for any version requirements
for /F %%r in (.\python\requirements.txt) do (
call :substr "%%r" !package! _substr
rem check if a given line refers to a package we are about to upgrade
if "%%r" NEQ !_substr! (
rem check if the line contains more than just a package name
if "%%r" NEQ "!package!" (
rem set requirements to what is contained in this line
echo requirements: %%r
set requirements=%%r
)
)
)
pip install --upgrade !requirements!
set /a "upgrade_count+=1"
echo.
)
if !upgrade_count!==0 (
echo All packages are up to date.
) else (
type pip-upgrade-outdated.txt
)
exit /b
:substr
rem string substition done in a separate subroutine -
rem allows expand both variables in the substring syntax
set str_source=%1
set str_search=%2
rem replace str_search with an empty string.
rem return the result in the 3rd parameter, passed by reference from the caller.
set "%~3=!str_source:%str_search%=!"
exit /b