Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add frozen environment support #238

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/execnet/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ def _source_of_function(function):
args = sig.args
if not args or args[0] != "channel":
raise ValueError("expected first function argument to be `channel`")

closure = function.__closure__
codeobj = function.__code__

Expand Down
19 changes: 18 additions & 1 deletion src/execnet/gateway_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
class Popen2IOMaster(Popen2IO):
def __init__(self, args, execmodel):
PIPE = execmodel.subprocess.PIPE
if is_frozen_environment():
args[0] = str(sys.executable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is correct, we should not be mutating the input arguments like this, nor assuming the first argument is the interpreter. This class is public, and even if it was not the case, this is certainly surprising behavior.

Clients of this class should instead use sys.executable instead of just "python", for example here: https://github.com/AlexPaiva/execnet/blob/227da4174e349b0cc198619b5fd186c6f137df82/src/execnet/gateway_io.py#L86C5-L86C43

os.environ["EXECNET_SPAWNING_SUBPROCESS"] = "1"
self.popen = p = execmodel.subprocess.Popen(args, stdout=PIPE, stdin=PIPE)
super().__init__(p.stdin, p.stdout, execmodel=execmodel)

Expand Down Expand Up @@ -53,8 +56,22 @@ def shell_split_path(path):
return shlex.split(path)


def is_frozen_environment():
"""Check if running in a Frozen environment."""
return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")


def get_python_executable():
"""Get the correct Python interpreter path."""
if is_frozen_environment():
return os.environ.get("PYTHON_EXECUTABLE", "python")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned, not clear to me why this is needed, seems to me we should always return sys.executable from here?

else:
return sys.executable


def popen_args(spec):
args = shell_split_path(spec.python) if spec.python else [sys.executable]
python_executable = get_python_executable()
args = shell_split_path(spec.python) if spec.python else [python_executable]
args.append("-u")
if spec.dont_write_bytecode:
args.append("-B")
Expand Down