TL; DR

Pour:

  1. pythonEtjavascriptDeruntime(En gros, c'estcpython[Non, pas du tout.cython!]EtNode.js)Tout est prêt.
  2. Le langage auxiliaire utilise des paquets complexes(Par exemplepythonÇa marche.numpy、javascriptAvec un peu deNode.jsDeC++Extension, etc.)
  3. Si nécessaire pour l'efficacité opérationnelle:
    • pythonAvecjavascriptIl n'y a pas beaucoup d'interaction entre,L'objet transmis n'est pas trop grand、C'est trop compliqué.,De préférence tous les objets sérialisables
    • javascriptLa proportion n'est pas si faible.Sinon,pythonTunejsEt si,DémarrageNode.jsLe Sous - processus est plus lent que le programme réel;jsTunepythonEt si,Parce quejsVite!,Il faut beaucoup de temps pour attendrepythonAllez..
  4. Parce queIPCLe taux approximatif synchronisera l'entrée et la sortie avec le thread,Moins de langue principale, plus de processus、Programmation simultanée comme thread

Il y a une bibliothèque.!Il y a une bibliothèque.!Il y a une bibliothèque.!

pythonTunejavascript

  • JSPyBridgepip install javascript

    • Avantages:

      1. L'auteur maintient toujours ,Retourissue Et les mises à jour sont assez rapides .
      2. Prise en charge des pythonEtnodeVersion,Facile à installer
      3. Support de base pour les appels mutuels , Y compris les fonctions de liaison ou de rappel .
    • Inconvénients: Absence de mécanisme de destruction raisonnable ,import javascript Est considéré comme une connexion JSFin, Tous les Threads multithreads à utiliser sont initialisés .Sipython Le programme principal veut redémarrer la paire JSConnexion à, Ou le programme principal utilise plusieurs processus , Je veux me connecter une fois par processus JS,C'est difficile à faire., Il est facile de faire des erreurs .
  • PyExecJSpip install PyExecJS, Les anciens articles techniques poussent ce paquet
    • Avantages: Soutien saufNode.jsAutresruntime,Par exemplePhantomJSQuelque chose comme ça.
    • Inconvénients: End of Life, L'auteur a arrêté la maintenance

javascriptTunepython

( Parce que ça ne correspond pas vraiment à mes besoins de projet , Donc je ne sais pas grand - chose )

Principes

Tout d'abord,, La méthode repose sur la prémisse que les deux langues ont été installées runtime, Et peut être appelé par la ligne de commande runtime Exécuter un fichier ou un script de chaîne de caractères .Par exemple,Chargez.cpython Après ça, on pourra passer par python a.pyPour courirpythonProcédure,Chargez.Node.jsAprès ça, on pourra passer parnode a.jsOunode -e "some script" Attends de courir JSProcédure.

Bien sûr.,Dans le cas le plus simple, Si nous n'avons besoin d'appeler qu'une seule langue secondaire , Et il n'y a pas d'interaction ( Ou une seule interaction au plus ), Alors trouvez un appel de méthode. CLIJusteOKC'est. Pour l'entrée dans la langue secondaire stdin Ou passer un paramètre en ligne de commande , Lire la sortie de la commande comme sortie du sous - langage .

Par exemple,pythonÇa marchesubprocess.Popen,subprocess.call,subprocess.check_outputOuos.systemQuelque chose comme ça.,Node.jsÇa marchechild_processLa méthode de Li,execOuforkQuelque chose comme ça..Il est important de noter que, Si d'autres paquets doivent être référencés ,Node.jsIl convient de noter quenode_modules Exécuter les instructions dans le répertoire où elles se trouvent ,python Attention au réglage PYTHONPATHVariables d'environnement.

# Need to set the working directory to the directory where `node_modules` resides if necessary
>>> import subprocess
>>> a, b = 1, 2
>>> print(subprocess.check_output(["node", "-e", f"console.log({a}+{b})"]))
b'3\n'
>>> print(subprocess.check_output(["node", "-e", f"console.log({a}+{b})"]).decode('utf-8'))
3
// Need to set PYTHONPATH in advance if necessary
const a = 1;
const b = 2;
const { execSync } = require("child_process");
console.log(execSync(`python -c "print(${a}+${b})"`));
//<Buffer 33 0a>
console.log(execSync(`python -c "print(${a}+${b})"`).toString());
//3
//

S'il y a des interactions complexes , Pour passer des objets complexes , Certains peuvent être sérialisés , Certains ne peuvent pas être sérialisés du tout ,Et alors??

Il s'agit essentiellement d'utiliser Communication inter - processus(IPC), Habituellement avec Tuyauterie(Pipe).Instdin,stdoutEtstderr Choisissez au moins un des trois pour construire le pipeline .

Supposons que j'utilisestdinDepythonVersjsTransmission des données,AvecstderrRéception des données, C'est à peu près comme ça. :

( Le pseudocode suivant n'est qu'indicatif , Pas rigoureusement testé , Utilisation pratique recommandée utilisation directe de la Bibliothèque )

  1. Créer une nouvelle sous - langue (Supposons queJS)Documentationpython-bridge.js: Ce fichier est constamment Lu stdin Et selon le message envoyé ,Traitement différent; Et si vous avez besoin d'imprimer un message ou de le transmettre object Pour la langue principale , Les sérialiser correctement et les écrire stdoutOustderr.
    process.stdin.on('data', data => {
    data.split('\n').forEach(line => {
    // Deal with each line
    // write message
    process.stdout.write(message + "\n");
    // deliver object, "$j2p" can be any prefix predefined and agreed upon with the Python side
    // just to tell python side that this is an object needs parsing
    process.stderr.write("$j2p sendObj "+JSON.stringify(obj)+"\n);
    });
    }
    process.on('exit', () => {
    console.debug('** Node exiting');
    });
  2. InpythonMoyenne,AvecPopen Ouvrir un sous - processus asynchrone , Et au moins un des sous - processus , Par canalisation . C'est comme :
    cmd = ["node", "--trace-uncaught", f"{os.path.dirname(__file__)}/python-bridge.js"]
    kwargs = dict(
    stdin=subprocess.PIPE,
    stdout=sys.stdout,
    stderr=subprocess.PIPE,
    )
    if os.name == 'nt':
    kwargs['creationflags'] = subprocess.CREATE_NO_WINDOW
    subproc = subprocess.Popen(cmd, **kwargs)
  3. Appelé au besoinJS, Ou besoin de donner JSLors de la transmission des données,Allez.subproc Écrire des informations sérialisées , Après l'écriture flush, Sinon, le tampon pourrait être écrit en premier :
    subproc.stdin.write(f"$p2j call funcName {json.dumps([arg1, arg2])}".encode())
    subproc.stdin.flush() # write immediately, not writing to the buffer of the stream
  4. Pour la tuyauterie stdout/stderr,Créer un nouveau thread, Dédié à la lecture et au traitement des données transmises . Est la conversion d'un objet en objet , Est l'impression directe d'informations générales au processus principal stderrOustdout.
    def read_stderr():
    while subproc.poll() is None:
    # when the subprocess is still alive, keep reading
    line = self.subproc.stderr.readline().decode('utf-8')
    if line.startswith('$j2p'):
    # receive special information
    _, cmd, line = line.split(' ', maxsplit=2)
    if cmd == 'sendObj':
    # For example, received an object
    obj = json.loads(line)
    else:
    # otherwise, write to stderr as it is
    sys.stderr.write(line) stderr_thread = threading.Thread(target=read_stderr, args=(), daemon=True)
    stderr_thread.start()

    C'est à cause de notrestdout Aucun tuyau n'a été construit ,Alors...node Par là stdout Ce qui est imprimé à l'intérieur sera imprimé directement à pythonDesys.stdout- Oui.,Ne vous en occupez pas vous - même..

  5. Parce que les fils sont asynchrones , Quand Savez - vous qu'un objet retourné par une fonction est arrivé ? La réponse est de synchroniser les fils ,Sémaphore(Semaphore)、Conditions(Condition),Événements(Event)Attendez un peu!,Tout va bien..ParpythonConditionsPar exemple:
    func_name_cv = threading.Condition()
    # use a flag and a result object in case some function has no result
    func_name_result_returned = False
    func_name_result = None def func_name_wrapper(arg1, arg2):
    # send arguments
    subproc.stdin.write(f"$p2j call funcName {json.dumps([arg1, arg2])}".encode())
    subproc.stdin.flush()
    # wait for the result
    with func_name_cv:
    if not func_name_result_returned:
    func_name_cv.wait(timeout=10000)
    # when result finally returned, reset the flag
    func_name_result_returned = False
    return func_name_result

    En même temps, Besoin de lire stderrLes fils deread_stderr Pour débloquer cette valeur de retour .Il est important de noter que,SiJS Duan est sorti par accident. ,subprocEt mourir., N'oubliez pas d'annuler le blocage dans le fil principal .

    def read_stderr():
    while subproc.poll() is None:
    # when the subprocess is still alive, keep reading
    # Deal with a line
    line = self.subproc.stderr.readline().decode('utf-8')
    if line.startswith('$j2p'):
    # receive special information
    _, cmd, line = line.split(' ', maxsplit=2)
    if cmd == 'sendObj':
    # acquire lock here to ensure the editing of func_name_result is mutex
    with func_name_cv:
    # For example, received an object
    func_name_result = json.loads(line)
    func_name_result_returned = True
    # unblock func_name_wrapper when receiving the result
    func_name_cv.notify()
    else:
    # otherwise, write to stderr as it is
    sys.stderr.write(line)
    # If subproc is terminated (mainly due to error), still need to unblock func_name_wrapper
    func_name_cv.notify()

    Bien sûr, c'est une version plus simple ,Parce queJS Les appels sont essentiellement linéaires , On peut donc savoir qu'il suffit d'en avoir un objectRetour de,Ça doit êtrefunc_name_wrapperRésultats correspondants. Si les fonctions sont nombreuses , La situation sera plus compliquée .

  6. Si tu veuxAnnulez.JSConnexion à, Vous devez d'abord fermer le Sous - processus , Et attendez de lire stdout/stderr Les fils de ,Enfin N'oubliez pas de fermer le tuyau .Et L'ordre de ces trois étapes ne peut pas être changé , Si vous fermez d'abord le tuyau , Lire le thread parce que stdout/stderr C'est fermé et une erreur s'est produite .
    subproc.terminate()
    stderr_thread.join()
    subproc.stdin.close()
    subproc.stderr.close()

Si c'est le cas, javascriptAppelezpython,C'est la même méthode,javascript Fang Oui. Node.jsEt si,Avecchild_process Les instructions de .

Avantages

  1. Tout ce qu'il faut, c'est un montage normal des deux côtés runtime Pour réaliser l'interaction , L'environnement de fonctionnement est relativement bon .
  2. Tant quepythonFang etjavascript Fang dans leurs runtime Ça va aller. , Il n'y a pas de problème à courir même après .( Sauf en cas de concurrence )
  3. Tous les paquets d'extension disponibles dans les deux langues sont essentiellement pris en charge .

Inconvénients

  1. QuandpythonAvecJavaScript Interactions fréquentes , Et quand l'information interactive est grande , Peut affecter l'efficacité du programme . Parce que ce n'est que par 3 Les tuyaux sont mélangés pour traiter les informations générales à imprimer 、pythonAvecjs Objets interactifs 、Appels de fonctions, etc., Les communications coûtent cher .
  2. Pour qu'un autre sous - processus exécute le Sous - langage runtime, Ça va prendre du temps et de l'espace .

PythonAvecJavascript Explication super détaillée de l'appel mutuel (2022Année1Mise à jour du mois)(Un.)Justification Part 1 - Par sous - processus et communication inter - processus (IPC)Autre article Afghanistan

  1. IOS ObjectEtjavaScriptAppel mutuel

    InIOS Parfois utilisé dans le développement ObjectEtjavaScriptAppel mutuel, Les procédures détaillées sont les suivantes: : 1. ObjectEn coursjavascriptCode, C'est plus simple , Apple offre un excellent moyen de - (NSString ...

  2. Hybrid AppEn mode développement, IOS/Android Et JavaScript Mode d'appel mutuel

    IOS:Objective-C Et JavaScript Appels mutuels iOS7Avant,iOS SDK Pas d'offre Native js Appelez native Code API.Mais UIWebView Un dele ...

  3. AndroidEtJavaScript Méthode d'appel mutuel

    Adresse de reproduction:http://www.jb51.net/article/77206.htm Cet article présente principalementAndroidEtJavaScript Méthode d'appel mutuel , L'exemple analyse AndroidDeWebViewMise en œuvre ...

  4. androidAvecjavascriptAppel mutuel

    La section suivante décrit androidEtjavascript Comment s'appellent - ils les uns les autres? ,Comme ça.UI L'interface est beaucoup plus simple à concevoir ,EtUI Conçu pour traverser les plateformes . Il y a beaucoup de web app La réception est encadrée ,Par exemple,senchaEtjque ...

  5. Python Notes d'apprentissage de base(Version super détaillée)

    1.Variables pythonLa variable moyenne est simple,Il n'est pas nécessaire de spécifier le type de données,Il suffit d'utiliser directement la définition du signe égal.pythonLa variable contient l'adresse mémoire,C'est là que cette valeur existe en mémoire,Si cette variable est assignée à une autre variable, Avant que la nouvelle variable passe ...

  6. Projet Open SourceScriptGate,DelphiAvecJavaScript Les artefacts qui s'appellent

    ScriptGateEst une réalisationTWebBrowserOui.JavaScriptEtDelphi Bibliothèques dont le Code s'appelle mutuellement ,C'est ici.:https://bitbucket.org/freeonterminate/sc ...

  7. python - Appels mutuels de fonctions Et Champ d'application de la variable

    # -*- coding:utf-8 -*- '''@project: [email protected]: [email protected]: study_ Appels mutuels de fonctions et portée des variables [email protected]: PyCharm C ...

  8. pythonModule-- Comment se rappeler les modules écrits par eux - mêmes

    Un.. Deux façons dont les modules s'appellent les uns les autres lorsqu'ils appellent des pairs import module print(module.add(3,8)) from module import add print(add(2,4)) Même ordre ...

  9. UIWebViewAvecJavaScriptAppel mutuel

    UIWebViewAvecJavaScriptCes choses UIWebView- Oui.IOS SDK Contrôle du maillage de rendu moyen , Lors de l'affichage d'une page Web ,On peut.hack La page Web affiche ensuite ce que vous voulez afficher .C'est là quejavascriptOui. ...

  10. Keras Code très détaillé LSTMDétails de la mise en œuvre

    1.Commençons par comprendrekerasDansEmbeddingCouche:from keras.layers.embeddings import Embedding: EmbeddingLes paramètres sont les suivants:: Taille d'entrée:(batc ...

Recommandation aléatoire

  1. SQLIndex ajouter

    EXPLAIN select * from view_agzsaycommont  where id >0

  2. [deviceoneDéveloppement]-Puzzle Games

    Un..Introduction Jeux de puzzle , Une image peut être chargée à partir de la galerie locale ,Remplir9- Oui.ImageView, L'autre concerne TimerChronométrage. Contrôle de la Bibliothèque . Chaque grille est le même contrôle , Ajouté dynamiquement à la page d'accueil ,Après initialisation,RéponsetouchÉvénements, Plus tard ...

  3. Modifierxubuntu14.04( Il en va de même pour ubuntu)En bas.Eclipse Note noire par défaut

    Entrée du terminal:sudo gedit /usr/share/themes/Ambiance/gtk-2.0/gtkrc La première ligne voit ce qui suit : gtk-color-scheme = "base_c ...

  4. JSPDe7Commandes d'action

    Les instructions d'action sont différentes des instructions de compilation,Les instructions de compilation sont des notificationsServletInformations sur le traitement du moteur,Et l'action de l'exécution de la connaissance de l'instruction d'action.Les instructions de compilationJSPCompilé enServletÇa marche quand,Les instructions de traitement peuvent généralement être remplacées parJSPScript,Sa connaissanceJSPNormes pour les scripts ...

  5. Oracle Fonction d'analyse &quot;ORA-30485: Perdu dans la description de la fenêtre ORDER BY Expression&quot;

    Plusieurs fonctions d'analyse liées à l'ordre row_number.rank.dense_rank.leadEtlagDeoverDans la fenêtre,Il doit y en avoir un.order_by_clause. D'autres comme :first_value.last_v ...

  6. wsdlLocation Pouvez - vous écrire la force relative du projet

    Si le Code du client utilise wsdlMots générés, Cette adresse vient de wsdlDescription<service>À l'intérieur.<location>Acquis, Si l'adresse de service a été changée pendant le développement , Ça ne peut être modifié qu'à la main. , On dirait qu'il n'y a qu'un seul endroit ...

  7. GoogleDeJava Utilisation fréquente des bibliothèques de classe Guava

    Guava Le chinois signifie Grenade,Le projet est Google Un projet Open source pour,Y compris beaucoup Google Core Java Utilisation fréquente de la Bibliothèque . 1. Outils de base [Basic utilities]     UtiliserJava ...

  8. Insertion Sort List Leetcode

    Sort a linked list using insertion sort. J'a i habilement mis en place un noeud de tête temporaire class Solution { public: ListNode* insert ...

  9. DOCKER De commencer à abandonner(Trois)

    Utiliserdocker create [image-name] Créer un conteneur Créer unnginxConteneur miroir, Comme aucun paramètre n'a été spécifié , Paramètres par défaut de l'utilité du conteneur , Ne démarre pas après la création ,Et mettre le récipientIDSortie vers le terminal, S'il n'y a pas de miroir local ...

  10. animate.cssUtilisation de

    Les mots avant animate.cssC'est une utilisationCSS3Deanimation Effets d'animation produits CSSEnsemble, Il y a beaucoup d'animations préférées , Et très simple à utiliser .Cet article détailleraanimate.cssUtilisation de Introduction anim ...