-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Issue 5180 tempfiles are leak in tmp #5210
Conversation
pipenv/environment.py
Outdated
"u'platinclude': u'{{0}}'.format(distutils.sysconfig.get_python_inc(" | ||
"plat_specific=1)) }}; value = u'{{0}}'.format(json.dumps(paths));" | ||
"fh = io.open('{0}', 'w'); fh.write(value); fh.close()" | ||
"import distutils.sysconfig, io, json, sys; paths = {u'include': " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize you are just refactoring existing code, but now I notice this usage of distutils which is totally deprecated. I wonder what the correct transformation of this usage would be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of writing to a file, I refactor so it print out to the stdout
directly.
Because the filename should not be passed to string as variable anymore, I deleted some unnecessary curly braces.
The ouptut code should look like this
import distutils.sysconfig, io, json, sys
paths = {
u'include': u'{0}'.format(distutils.sysconfig.get_python_inc(plat_specific=0)),
u'platinclude': u'{0}'.format(distutils.sysconfig.get_python_inc(plat_specific=1))
}
value = u'{0}'.format(json.dumps(paths))
print(value)
Sorry, I was copied the ouptut from build_command
instead of get_include_path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you said, I tried to remove distutils.sysconfig and use sysconfig instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since sysconfig.get_path
does not raise exception like distutils.sysconfig
, the c.returncode
is always 0
. Therefore, those lines below could be refactored
Lines 393 to 415 in 75b77eb
command = [self.python, "-c", py_command.format(tmpfile_path)] | |
c = subprocess_run(command) | |
if c.returncode == 0: | |
paths = {} | |
with open(tmpfile_path, "r", encoding="utf-8") as fh: | |
paths = json.load(fh) | |
if "purelib" in paths: | |
paths["libdir"] = paths["purelib"] = make_posix(paths["purelib"]) | |
for key in ( | |
"platlib", | |
"scripts", | |
"platstdlib", | |
"stdlib", | |
"include", | |
"platinclude", | |
): | |
if key in paths: | |
paths[key] = make_posix(paths[key]) | |
return paths | |
else: | |
click.secho(f"Failed to load paths: {c.stderr}", fg="yellow") | |
click.secho(f"Output: {c.stdout}", fg="yellow") | |
return None |
I noticed that Lines 217 to 240 in 75b77eb
|
@dqkqd Looks good, nice work! -- do you mind adding a news fragment explaining your change? |
@dqkqd Thanks for adding a news fragment -- the linter wants there to be a newline at the end of that news fragment. |
Sorry, I forgot to run |
Sorry for the mess with the fragment file. I fixed it again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -384,18 +376,13 @@ def get_paths(self) -> Optional[Dict[str, str]]: | |||
:return: The python paths for the environment | |||
:rtype: Dict[str, str] | |||
""" | |||
tmpfile = vistir.path.create_tracked_tempfile(suffix=".json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bonus points for removing usage of vistir 💯
@dqkqd I just want to say again what awesome work you did with this change -- to be able to eliminate some file usage altogether is amazing for performance, and I think we see that in the new measurements that @oz123 pointed me at this evening, which are provided by the head of Lincoln Loop: https://lincolnloop.github.io/python-package-manager-shootout/ |
@matteius Thank you so much. This is my first time contributing to open sources. Sorry for messing up with git. |
Thanks for creating such beautiful project!
The issue
I'm trying to fix #5180
get_paths
,get_lib_paths
,get_include_path
functions create new .json files to store output called fromsubprocess_run
without closing it.The fix
Because the .json file is used only inside the function call. I have two solutions for this.
stdout
.As these functions contain many returns, there will be a lot of duplicated codes to delete the file. So I tend to the second solution.
As far as I know,
subprocess_run
executepy_command
, and if it failed to execute,c.stdout
will be printed out to console. But thepy_command
does not print anything out. Thereforec.stdout
is always empty.Instead of creating new temporary file, I think it is better to use
c.stdout
to write directly topaths
variable.The checklist
news/
directory to describe this fix with the extension.bugfix
,.feature
,.behavior
,.doc
..vendor
. or.trivial
(this will appear in the release changelog). Use semantic line breaks and name the file after the issue number or the PR #.