Skip to content

Commit

Permalink
v1.1: 2.81+ pip support
Browse files Browse the repository at this point in the history
  • Loading branch information
NumesSanguis committed Feb 10, 2020
1 parent c6d647c commit 6f8368f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Blender 2.8x add-on that allows streaming of data (from another computer) into Blender over ZeroMQ sockets,
**without** freezing the interface (publisher-subscriber pattern).

## Update
- v1.1 (2020-02-10) - **Blender 2.81+ pip support**: In Blender 2.81 pip is enabled by default.
This update takes that behavior into account. If the `Enable pip & install pyzmq` button fails, it still executes
`ensurepip.bootstrap()`. Restart Blender and try again, it will work this time
(on Windows make sure you run with admin rights).

## Overview
Blender is very powerful software, but if you run your own code that's a bit heavy, you quickly make the interface
unresponsive. I.e freezing the interface.
Expand Down
44 changes: 37 additions & 7 deletions blendzmq_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,12 @@ def execute(self, context): # execute() is called when running the operator.

# pip in Blender:
# https://blender.stackexchange.com/questions/139718/install-pip-and-packages-from-within-blender-os-independently/
# pip 2.81 issues: https://developer.blender.org/T71856

# no pip enabled by default version < 2.81
install_props.install_status = "Preparing to enable pip..."
self.report({'INFO'}, "Preparing to enable pip...")
if bpy.app.version[0] == 2 and bpy.app.version[1] < 81:
install_props.install_status = "Preparing to enable pip..."
# find python binary OS independent (Windows: bin\python.exe; Linux: bin/python3.7m)
py_path = Path(sys.prefix) / "bin"
py_exec = str(next(py_path.glob("python*"))) # first file that starts with "python" in "bin" dir
Expand All @@ -163,8 +165,22 @@ def execute(self, context): # execute() is called when running the operator.

# from 2.81 pip is enabled by default
else:
import ensurepip
ensurepip.bootstrap()
try:
# will likely fail the first time, but works after `ensurepip.bootstrap()` has been called once
import pip
except ModuleNotFoundError as e:
# only first attempt will reach here
print("Pip import failed with: ", e)
install_props.install_status += "\nPip not activated, trying bootstrap()"
self.report({'ERROR'}, "Pip not activated, trying bootstrap()")
try:
import ensurepip
ensurepip.bootstrap()
except: # catch *all* exceptions
e = sys.exc_info()[0]
install_props.install_status += "\nPip not activated, trying bootstrap()"
self.report({'ERROR'}, "Pip not activated, trying bootstrap()")
print("bootstrap failed with: ", e)
py_exec = bpy.app.binary_path_python

# TODO check permission rights
Expand All @@ -173,17 +189,31 @@ def execute(self, context): # execute() is called when running the operator.

install_props.install_status += "\nPip activated! Updating pip..."
self.report({'INFO'}, "Pip activated! Updating pip...")
if subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip"]) != 0:
install_props.install_status += "\nCouldn't update pip."
self.report({'ERROR'}, "Couldn't update pip.")

# pip update
try:
print("Trying pip upgrade")
output = subprocess.check_output([py_exec, '-m', 'pip', 'install', '--upgrade', 'pip'])
print(output)
except subprocess.CalledProcessError as e:
install_props.install_status += "\nCouldn't update pip. Please restart Blender and try again."
self.report({'ERROR'}, "Couldn't update pip. Please restart Blender and try again.")
print(e.output)
return {'CANCELLED'}
install_props.install_status += "\nPip working! Installing pyzmq..."
self.report({'INFO'}, "Pip working! Installing pyzmq...")

if subprocess.call([py_exec, "-m", "pip", "install", "pyzmq"]) != 0:
# pyzmq pip install
try:
print("Trying pyzmq install")
output = subprocess.check_output([py_exec, '-m', 'pip', 'install', 'pyzmq'])
print(output)
except subprocess.CalledProcessError as e:
install_props.install_status += "\nCouldn't install pyzmq."
self.report({'ERROR'}, "Couldn't install pyzmq.")
print(e.output)
return {'CANCELLED'}

install_props.install_status += "\npyzmq installed! READY!"
self.report({'INFO'}, "pyzmq installed! READY!")

Expand Down

0 comments on commit 6f8368f

Please sign in to comment.