0

Is there a way to perform a python import which is not atomic?

For instance, I have a file as follows:

# Filename: a.py
myvariable = 1
mylist = [1, 2, 3]
raise ImportError
donotimportthis = 5

I then have a separate file which does the following:

import a
a.myvariable == 1 # This is okay as it imported it
a.donotimportthis # <-- raise an exception as this is not imported.

I have a file which contains some python code, this follows the format of:

...variables...
import X

I do not have X installed nor do I want it however I do want the variables. Note: This file is autogenerated not by me but by a tool whose version is frozen.

Har
  • 3,727
  • 10
  • 41
  • 75
  • 3
    Smells like an XY problem. What would be your real use case for this, assuming it was possible? – DeepSpace Aug 15 '19 at 15:22
  • ill update the question. – Har Aug 15 '19 at 15:23
  • When an `ImportError` is raised, the name `a` is not defined - so no the importing script won't work – rdas Aug 15 '19 at 15:24
  • 1
    FWIW you can define `donotimportthis = 5` inside an `if __name__ == '__main__'` block, then it won't be visible for anything that imports `a.py` – DeepSpace Aug 15 '19 at 15:24
  • In response to your edit: change the autogeneration process: Let the tool autogenerate your module, and then post-process the module by deleting everything starting at `import X`. – Konrad Rudolph Aug 15 '19 at 15:26
  • I cannot change the autogeneration it is a proprietary tool which is closed source. – Har Aug 15 '19 at 15:30
  • 1
    @Har Reread my comment: change the module source code *after* the autogen tool has run. This does not require you to make changes to the tool. – Konrad Rudolph Aug 15 '19 at 15:35
  • 1
    fithy hack, create an empty file called `X.py` – Chris_Rands Aug 15 '19 at 15:38

3 Answers3

2

Two choices, in descending order of preference:

  1. Change the autogeneration process. Instead of invoking proprietary_autogen_process, invoke custom_autogen_wrapper. This wrapper in turn first invokes the proprietary third-party tool, and then modifies the produced module source code by searching for the code that imports module X, and deletes everything after it.

    This is relatively straightforward. You just need to take some care to not introduce false positives or false negatives by performing too loose (or too strict) matching of the import code. Ideally you’d use an AST rewriter but that’s probably overkill; a regular expression search for import X might work, although it will yield wrong results if this text appears inside a comment, string literal or inside a method which isn’t executed.

  2. Generate a stub module X in a location where it will be found by the autogenerated module when importing the latter. I don’t recommend this because it’s tedious: You probably can’t just generate an empty module, since the autogenerated module will want to use X. You need to generate meaningful method stubs.

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Thanks Konrad, I think I agree with your first answer, it seems to be a compromise, I would as @Neil mentioned, read the file into memory and perform the operation with an AST rewriter :) – Har Aug 15 '19 at 15:43
1

You can do specific imports with

from a import myvariable

EDIT: The above won't work if anything that is flat in the file raises an error. If you have no way to edit the imported file then I don't know if there is a (resonable) solution to this. Sorry didn't realise. (an unreasonable solution would be to read in the file as text, slice it, and then run eval on it).

Or, as mentioned in the comments, put the stuff you don't want under

if __name__=="__main__":
    <here>

Then it will only be invoked if you run the file directly.

Neil
  • 3,020
  • 4
  • 25
  • 48
0

What you can do is removing the donotimportthis variable at the end of the module, as follows: del donotimportthis. I hope it helps

ivallesp
  • 2,018
  • 1
  • 14
  • 21