Install Python script requirements

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
6
down vote

favorite












Sometimes I download a Python script (from a trusted source), and can't run it because of missing dependencies, which I have to install one by one (no requirements.txt is provided). I'm looking for a way to automate this process. It's similar to this question, but I'd like to infer the requirements automatically. I.e. given the script, install all the packages it's importing.



If myscript.py looks like:



import pandas
import tensorflow as tf
from keras.models import Sequential


Then after running the script (e.g. bash extract_requirements.sh myscript.py) pandas, tensorflow, and keras will be installed.



Of course, a script can call another script, which has its own dependencies, package names don't always match to import names etc. So it's not a perfect solution, but better than nothing.



What I'm using now is a command-line script:



#!/env bash

set -u

usage()
echo "$0" '[-d] <MY_SCRIPT>'
cat <<-EOF
options:
-d Dry-run. Print package names without installing.
EOF
exit 1;


(( $# == 0 )) && usage
dry=0
if [[ "$1" == '-d' ]]; then
dry=1
shift
fi
(( $# != 1 )) && usage

script="$1"
imports1=$(egrep '^s*froms+[a-zA-Z_.-]+simport' "$script" | cut -f2 -d' ' | cut -f1 -d'.')
imports2=$(egrep '^s*imports+[a-zA-Z_-]+' "$script" | cut -f2 -d' ')
all=$(printf "$imports1n$imports2" | sort -u)
if (( dry )); then
echo "$all" | xargs -L 1 echo
else
echo "$all" | xargs -L 1 sudo pip install
fi

set +u


I was wondering if I'm missing some import cases, and more importantly, whether there's a simpler, more python-ic, solution.







share|improve this question





















  • 'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
    – Daniel
    Apr 15 at 16:36











  • @Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
    – dimid
    Apr 15 at 16:40
















up vote
6
down vote

favorite












Sometimes I download a Python script (from a trusted source), and can't run it because of missing dependencies, which I have to install one by one (no requirements.txt is provided). I'm looking for a way to automate this process. It's similar to this question, but I'd like to infer the requirements automatically. I.e. given the script, install all the packages it's importing.



If myscript.py looks like:



import pandas
import tensorflow as tf
from keras.models import Sequential


Then after running the script (e.g. bash extract_requirements.sh myscript.py) pandas, tensorflow, and keras will be installed.



Of course, a script can call another script, which has its own dependencies, package names don't always match to import names etc. So it's not a perfect solution, but better than nothing.



What I'm using now is a command-line script:



#!/env bash

set -u

usage()
echo "$0" '[-d] <MY_SCRIPT>'
cat <<-EOF
options:
-d Dry-run. Print package names without installing.
EOF
exit 1;


(( $# == 0 )) && usage
dry=0
if [[ "$1" == '-d' ]]; then
dry=1
shift
fi
(( $# != 1 )) && usage

script="$1"
imports1=$(egrep '^s*froms+[a-zA-Z_.-]+simport' "$script" | cut -f2 -d' ' | cut -f1 -d'.')
imports2=$(egrep '^s*imports+[a-zA-Z_-]+' "$script" | cut -f2 -d' ')
all=$(printf "$imports1n$imports2" | sort -u)
if (( dry )); then
echo "$all" | xargs -L 1 echo
else
echo "$all" | xargs -L 1 sudo pip install
fi

set +u


I was wondering if I'm missing some import cases, and more importantly, whether there's a simpler, more python-ic, solution.







share|improve this question





















  • 'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
    – Daniel
    Apr 15 at 16:36











  • @Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
    – dimid
    Apr 15 at 16:40












up vote
6
down vote

favorite









up vote
6
down vote

favorite











Sometimes I download a Python script (from a trusted source), and can't run it because of missing dependencies, which I have to install one by one (no requirements.txt is provided). I'm looking for a way to automate this process. It's similar to this question, but I'd like to infer the requirements automatically. I.e. given the script, install all the packages it's importing.



If myscript.py looks like:



import pandas
import tensorflow as tf
from keras.models import Sequential


Then after running the script (e.g. bash extract_requirements.sh myscript.py) pandas, tensorflow, and keras will be installed.



Of course, a script can call another script, which has its own dependencies, package names don't always match to import names etc. So it's not a perfect solution, but better than nothing.



What I'm using now is a command-line script:



#!/env bash

set -u

usage()
echo "$0" '[-d] <MY_SCRIPT>'
cat <<-EOF
options:
-d Dry-run. Print package names without installing.
EOF
exit 1;


(( $# == 0 )) && usage
dry=0
if [[ "$1" == '-d' ]]; then
dry=1
shift
fi
(( $# != 1 )) && usage

script="$1"
imports1=$(egrep '^s*froms+[a-zA-Z_.-]+simport' "$script" | cut -f2 -d' ' | cut -f1 -d'.')
imports2=$(egrep '^s*imports+[a-zA-Z_-]+' "$script" | cut -f2 -d' ')
all=$(printf "$imports1n$imports2" | sort -u)
if (( dry )); then
echo "$all" | xargs -L 1 echo
else
echo "$all" | xargs -L 1 sudo pip install
fi

set +u


I was wondering if I'm missing some import cases, and more importantly, whether there's a simpler, more python-ic, solution.







share|improve this question













Sometimes I download a Python script (from a trusted source), and can't run it because of missing dependencies, which I have to install one by one (no requirements.txt is provided). I'm looking for a way to automate this process. It's similar to this question, but I'd like to infer the requirements automatically. I.e. given the script, install all the packages it's importing.



If myscript.py looks like:



import pandas
import tensorflow as tf
from keras.models import Sequential


Then after running the script (e.g. bash extract_requirements.sh myscript.py) pandas, tensorflow, and keras will be installed.



Of course, a script can call another script, which has its own dependencies, package names don't always match to import names etc. So it's not a perfect solution, but better than nothing.



What I'm using now is a command-line script:



#!/env bash

set -u

usage()
echo "$0" '[-d] <MY_SCRIPT>'
cat <<-EOF
options:
-d Dry-run. Print package names without installing.
EOF
exit 1;


(( $# == 0 )) && usage
dry=0
if [[ "$1" == '-d' ]]; then
dry=1
shift
fi
(( $# != 1 )) && usage

script="$1"
imports1=$(egrep '^s*froms+[a-zA-Z_.-]+simport' "$script" | cut -f2 -d' ' | cut -f1 -d'.')
imports2=$(egrep '^s*imports+[a-zA-Z_-]+' "$script" | cut -f2 -d' ')
all=$(printf "$imports1n$imports2" | sort -u)
if (( dry )); then
echo "$all" | xargs -L 1 echo
else
echo "$all" | xargs -L 1 sudo pip install
fi

set +u


I was wondering if I'm missing some import cases, and more importantly, whether there's a simpler, more python-ic, solution.









share|improve this question












share|improve this question




share|improve this question








edited Apr 16 at 2:56









Jamal♦

30.1k11114225




30.1k11114225









asked Apr 15 at 16:02









dimid

1966




1966











  • 'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
    – Daniel
    Apr 15 at 16:36











  • @Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
    – dimid
    Apr 15 at 16:40
















  • 'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
    – Daniel
    Apr 15 at 16:36











  • @Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
    – dimid
    Apr 15 at 16:40















'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
– Daniel
Apr 15 at 16:36





'Pythonic' applies more to pieces of Python code than to the language. Are you suggesting you might rewrite this in Python, or are you looking for tools provided by the Python Software Foundation that do this more cleanly?
– Daniel
Apr 15 at 16:36













@Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
– dimid
Apr 15 at 16:40




@Coal_ Yes, I was hoping there's a standard way to do it in python, rather than parsing python code in bash.
– dimid
Apr 15 at 16:40










1 Answer
1






active

oldest

votes

















up vote
4
down vote



accepted










!!! Use this at your own risk. Fiddling with user's packages is scary business !!!



You can monkey-patch the builtin import statement and upon encountering ModuleNotFoundError install whatever dependency is missing. Here is a small example for a script.py. You can of course extend this to feature multiple files or dynamically use the file given as input.



import builtins
import pip
old_import = __import__

def my_import(name, globals=None, locals=None, fromlist=(), level=0):
if globals["__name__"] == "script":
try:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
except ModuleNotFoundError:
builtins.__import__, temp = old_import, builtins.__import__
pipcode = pip.main(['install', name])
if pipcode != 0:
builtins.__import__ = temp
raise
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
builtins.__import__ = temp
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)

return return_args

builtins.__import__ = my_import

import script


and the script.py is your custom script:



import os
from time import time

import argh # this should be installed

print(time())


Note: People sometimes do things like:



try:
import optional_module
except ImportError:
pass # optional all cool


Above code patches import itself. If you remove the if that limits install powers to script you allow recursive installation for everything that is imported. Ever. Even if it is an optional dependency for a 4th level dependency test case of script pip will try to install it.






share|improve this answer























  • Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
    – dimid
    Apr 15 at 20:56










  • @dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
    – FirefoxMetzger
    Apr 16 at 4:05










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192123%2finstall-python-script-requirements%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
4
down vote



accepted










!!! Use this at your own risk. Fiddling with user's packages is scary business !!!



You can monkey-patch the builtin import statement and upon encountering ModuleNotFoundError install whatever dependency is missing. Here is a small example for a script.py. You can of course extend this to feature multiple files or dynamically use the file given as input.



import builtins
import pip
old_import = __import__

def my_import(name, globals=None, locals=None, fromlist=(), level=0):
if globals["__name__"] == "script":
try:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
except ModuleNotFoundError:
builtins.__import__, temp = old_import, builtins.__import__
pipcode = pip.main(['install', name])
if pipcode != 0:
builtins.__import__ = temp
raise
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
builtins.__import__ = temp
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)

return return_args

builtins.__import__ = my_import

import script


and the script.py is your custom script:



import os
from time import time

import argh # this should be installed

print(time())


Note: People sometimes do things like:



try:
import optional_module
except ImportError:
pass # optional all cool


Above code patches import itself. If you remove the if that limits install powers to script you allow recursive installation for everything that is imported. Ever. Even if it is an optional dependency for a 4th level dependency test case of script pip will try to install it.






share|improve this answer























  • Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
    – dimid
    Apr 15 at 20:56










  • @dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
    – FirefoxMetzger
    Apr 16 at 4:05














up vote
4
down vote



accepted










!!! Use this at your own risk. Fiddling with user's packages is scary business !!!



You can monkey-patch the builtin import statement and upon encountering ModuleNotFoundError install whatever dependency is missing. Here is a small example for a script.py. You can of course extend this to feature multiple files or dynamically use the file given as input.



import builtins
import pip
old_import = __import__

def my_import(name, globals=None, locals=None, fromlist=(), level=0):
if globals["__name__"] == "script":
try:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
except ModuleNotFoundError:
builtins.__import__, temp = old_import, builtins.__import__
pipcode = pip.main(['install', name])
if pipcode != 0:
builtins.__import__ = temp
raise
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
builtins.__import__ = temp
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)

return return_args

builtins.__import__ = my_import

import script


and the script.py is your custom script:



import os
from time import time

import argh # this should be installed

print(time())


Note: People sometimes do things like:



try:
import optional_module
except ImportError:
pass # optional all cool


Above code patches import itself. If you remove the if that limits install powers to script you allow recursive installation for everything that is imported. Ever. Even if it is an optional dependency for a 4th level dependency test case of script pip will try to install it.






share|improve this answer























  • Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
    – dimid
    Apr 15 at 20:56










  • @dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
    – FirefoxMetzger
    Apr 16 at 4:05












up vote
4
down vote



accepted







up vote
4
down vote



accepted






!!! Use this at your own risk. Fiddling with user's packages is scary business !!!



You can monkey-patch the builtin import statement and upon encountering ModuleNotFoundError install whatever dependency is missing. Here is a small example for a script.py. You can of course extend this to feature multiple files or dynamically use the file given as input.



import builtins
import pip
old_import = __import__

def my_import(name, globals=None, locals=None, fromlist=(), level=0):
if globals["__name__"] == "script":
try:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
except ModuleNotFoundError:
builtins.__import__, temp = old_import, builtins.__import__
pipcode = pip.main(['install', name])
if pipcode != 0:
builtins.__import__ = temp
raise
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
builtins.__import__ = temp
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)

return return_args

builtins.__import__ = my_import

import script


and the script.py is your custom script:



import os
from time import time

import argh # this should be installed

print(time())


Note: People sometimes do things like:



try:
import optional_module
except ImportError:
pass # optional all cool


Above code patches import itself. If you remove the if that limits install powers to script you allow recursive installation for everything that is imported. Ever. Even if it is an optional dependency for a 4th level dependency test case of script pip will try to install it.






share|improve this answer















!!! Use this at your own risk. Fiddling with user's packages is scary business !!!



You can monkey-patch the builtin import statement and upon encountering ModuleNotFoundError install whatever dependency is missing. Here is a small example for a script.py. You can of course extend this to feature multiple files or dynamically use the file given as input.



import builtins
import pip
old_import = __import__

def my_import(name, globals=None, locals=None, fromlist=(), level=0):
if globals["__name__"] == "script":
try:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
except ModuleNotFoundError:
builtins.__import__, temp = old_import, builtins.__import__
pipcode = pip.main(['install', name])
if pipcode != 0:
builtins.__import__ = temp
raise
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)
builtins.__import__ = temp
else:
return_args = old_import(name, globals=globals, locals=locals,
fromlist=fromlist, level=level)

return return_args

builtins.__import__ = my_import

import script


and the script.py is your custom script:



import os
from time import time

import argh # this should be installed

print(time())


Note: People sometimes do things like:



try:
import optional_module
except ImportError:
pass # optional all cool


Above code patches import itself. If you remove the if that limits install powers to script you allow recursive installation for everything that is imported. Ever. Even if it is an optional dependency for a 4th level dependency test case of script pip will try to install it.







share|improve this answer















share|improve this answer



share|improve this answer








edited Apr 16 at 8:05









Daniel

4,1132836




4,1132836











answered Apr 15 at 20:28









FirefoxMetzger

74628




74628











  • Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
    – dimid
    Apr 15 at 20:56










  • @dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
    – FirefoxMetzger
    Apr 16 at 4:05
















  • Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
    – dimid
    Apr 15 at 20:56










  • @dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
    – FirefoxMetzger
    Apr 16 at 4:05















Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
– dimid
Apr 15 at 20:56




Thanks, a nice pythonic solution, but I rather not to hardcode the name of the script.
– dimid
Apr 15 at 20:56












@dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
– FirefoxMetzger
Apr 16 at 4:05




@dimid This is just a small example to demonstrate the idea. You can extend this, e.g. globbing a folder for filenames which are okay to install or passing in the name of the script as input argument.
– FirefoxMetzger
Apr 16 at 4:05












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192123%2finstall-python-script-requirements%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation