Search code examples
pythonrubyrubypython

RubyPython imports


I'm fairly new to both python and ruby.

I've created a python script that imports it's dependencies like this:

import sys
sys.path.append("/usr/share/anki")
from anki import Collection
from anki.importing import TextImporter

How do I achieve the same functionality in RubyPython? Among other things, I've tried:

RubyPython.start

sys = RubyPython.import("sys")
sys.path.append("/usr/share/anki")
Collection = RubyPython.import("anki.Collection")
TextImporter = RubyPython.import("anki.importing.TextImporter")

RubyPython.stop

Which gives me an error: `import': AttributeError: 'module' object has no attribute 'argv' (RubyPython::PythonError) for the line for anki.Collection import.

I've also tried something like this:

RubyPython.start

sys = RubyPython.import("sys")
sys.path.append("/usr/share/anki/anki")
Collection = RubyPython.import("collection")
TextImporter = RubyPython.import("anki.importing.TextImporter")

RubyPython.stop

Which gives me an error: `import': ImportError: No module named anki.lang (RubyPython::PythonError) for the line for collection import. You can see from the source code for anki that this is the first thing imported in the collection.py file.


Solution

  • Python interpreter is embedded, thus it makes sense that some process-specific bits, e.g. sys.argv are not available.

    Here's a quick test without ruby:

    In [1]: import sys
    
    In [2]: del sys.argv
    
    In [3]: sys.path.append("anki")
    
    In [6]: import anki.Collection
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-6-ff326ec5c6ff> in <module>()
    ----> 1 import anki.Collection
    
    /dima/anki/anki/__init__.py in <module>()
         32 
         33 version="2.0.16" # build scripts grep this line, so preserve formatting
    ---> 34 from anki.storage import Collection
         35 __all__ = ["Collection"]
    
    /dima/anki/anki/storage.py in <module>()
          4 
          5 import os, copy, re
    ----> 6 from anki.lang import _
          7 from anki.utils import intTime, json
          8 from anki.db import DB
    
    /dima/anki/anki/lang.py in <module>()
        103 
        104 if not currentTranslation:
    --> 105     setLang("en_US", local=False)
    
    /dima/anki/anki/lang.py in setLang(lang, local)
         82 def setLang(lang, local=True):
         83     trans = gettext.translation(
    ---> 84         'anki', langDir(), languages=[lang], fallback=True)
         85     if local:
         86         threadLocal.currentLang = lang
    
    /dima/anki/anki/lang.py in langDir()
         75         os.path.abspath(__file__)), "locale")
         76     if not os.path.isdir(dir):
    ---> 77         dir = os.path.join(os.path.dirname(sys.argv[0]), "locale")
         78     if not os.path.isdir(dir):
         79         dir = "/usr/share/anki/locale"
    
    AttributeError: 'module' object has no attribute 'argv'
    

    Ideally your code should not rely on sys.argv, consider for example if your module is used by another project, you can make no assumption about what ends up in sys.argv.

    • If you want your code/resource directory, use os.path.dirname(__file__) instead(*)

    • if you really need sys.argv, inject fake array into sys before you import your modules.

    (*)Keep in mind that Python code can also be shipped as a zip, in which case you don't even have a directory in the traditional sense.